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 } ;
6
4
use objc2_foundation:: { NSDictionary , NSObject , NSString , NSURL } ;
7
5
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 ;
10
21
}
11
22
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] }
19
27
}
20
28
21
29
/// Deal with opening of browsers on iOS/tvOS/visionOS.
@@ -34,10 +42,11 @@ pub(super) fn open_browser_internal(
34
42
return Ok ( ( ) ) ;
35
43
}
36
44
37
- let app = app ( ) . ok_or ( Error :: new (
45
+ let mtm = MainThreadMarker :: new ( ) . ok_or ( Error :: new (
38
46
ErrorKind :: Other ,
39
- "UIApplication is null, can't open url " ,
47
+ "UIApplication must be retrieved on the main thread " ,
40
48
) ) ?;
49
+ let app = sharedApplication ( mtm) ;
41
50
42
51
// Create ns string class from our string
43
52
let url_string = NSString :: from_str ( url) ;
@@ -50,6 +59,6 @@ pub(super) fn open_browser_internal(
50
59
let options = NSDictionary :: new ( ) ;
51
60
52
61
// Open url
53
- open_url ( & app, & url_object, & options, None ) ;
62
+ open_url ( & app, & url_object, & options) ;
54
63
Ok ( ( ) )
55
64
}
0 commit comments