1- use crate :: { Browser , BrowserOptions , Error , ErrorKind , Result , TargetType } ;
2- use block2:: Block ;
3- use objc2:: rc:: Id ;
4- use objc2:: runtime:: Bool ;
5- use objc2:: { class, msg_send, msg_send_id} ;
1+ use std:: ffi:: c_void;
2+
3+ use objc2:: { class, msg_send, rc:: Retained , Encode , Encoding , MainThreadMarker } ;
64use objc2_foundation:: { NSDictionary , NSObject , NSString , NSURL } ;
75
8- fn app ( ) -> Option < Id < NSObject > > {
9- unsafe { msg_send_id ! [ class!( UIApplication ) , sharedApplication] }
6+ use crate :: { Browser , BrowserOptions , Error , ErrorKind , Result , TargetType } ;
7+
8+ /// Returns `UIApplication`
9+ #[ allow( non_snake_case) ]
10+ fn sharedApplication ( _mtm : MainThreadMarker ) -> Retained < NSObject > {
11+ unsafe { msg_send ! [ class!( UIApplication ) , sharedApplication] }
12+ }
13+
14+ /// Fake `block` to not have to depend on the `block2` crate just to set this to an empty/`None` block.
15+ #[ repr( transparent) ]
16+ struct FakeBlock ( * const c_void ) ;
17+
18+ // SAFETY: The type is `#[repr(transparent)]` over a pointer (same layout as `Option<&block::Block<...>>`).
19+ unsafe impl Encode for FakeBlock {
20+ const ENCODING : Encoding = Encoding :: Block ;
1021}
1122
12- fn open_url (
13- app : & NSObject ,
14- url : & NSURL ,
15- options : & NSDictionary ,
16- handler : Option < & Block < dyn Fn ( Bool ) > > ,
17- ) {
18- unsafe { msg_send ! [ app, openURL: url, options: options, completionHandler: handler] }
23+ #[ doc( alias = "openURL_options_completionHandler" ) ]
24+ fn open_url ( app : & NSObject , url : & NSURL , options : & NSDictionary ) {
25+ let fake_handler = FakeBlock ( std:: ptr:: null ( ) ) ;
26+ unsafe { msg_send ! [ app, openURL: url, options: options, completionHandler: fake_handler] }
1927}
2028
2129/// Deal with opening of browsers on iOS/tvOS/visionOS.
@@ -34,10 +42,11 @@ pub(super) fn open_browser_internal(
3442 return Ok ( ( ) ) ;
3543 }
3644
37- let app = app ( ) . ok_or ( Error :: new (
45+ let mtm = MainThreadMarker :: new ( ) . ok_or ( Error :: new (
3846 ErrorKind :: Other ,
39- "UIApplication is null, can't open url " ,
47+ "UIApplication must be retrieved on the main thread " ,
4048 ) ) ?;
49+ let app = sharedApplication ( mtm) ;
4150
4251 // Create ns string class from our string
4352 let url_string = NSString :: from_str ( url) ;
@@ -50,6 +59,6 @@ pub(super) fn open_browser_internal(
5059 let options = NSDictionary :: new ( ) ;
5160
5261 // Open url
53- open_url ( & app, & url_object, & options, None ) ;
62+ open_url ( & app, & url_object, & options) ;
5463 Ok ( ( ) )
5564}
0 commit comments