Skip to content

Commit

Permalink
feat(iOS): added custom URL schemes handling in the AppDelegate cla…
Browse files Browse the repository at this point in the history
…ss (#969)

* feat(iOS): added custom URL schemes handling in the `AppDelegate` class

Until now, only ["associated
domains"](https://developer.apple.com/documentation/xcode/supporting-associated-domains)
were handled, using the `application_continue` function, that implements [this
Swift method from the `UIApplicationDelegate`
class](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623072-application).

For [custom URL
schemes](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app),
I added a new `application_open_url` function that matches the signature of
[this other Swift
method](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application).

Most of the code of the pre-existing `application_continue` has been moved
into a separate `handle_deep_link` function so the new `application_open_url`
can call it as well.

I believe using the same `Event::Opened` event is appropriate in both
situations. Since the scheme is part of the URL, a listener can differentiate
between them if needed.

**Tauri:** since we are emitting the same `Event::Opened` event, this change
works automatically with the ["Deep Linking"
plugin](https://v2.tauri.app/plugin/deep-linking/) without further
modifications.

Custom URL schemes in mobile apps are essential, for example,
when dealing with OAuth redirect URLs.

* Update .changes/ios-custom-url-schemes.md

Co-authored-by: Jason Tsai <[email protected]>

---------

Co-authored-by: Jason Tsai <[email protected]>
  • Loading branch information
CampioneDev and pewsheen authored Sep 3, 2024
1 parent b6adbac commit ad652e5
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changes/ios-custom-url-schemes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tao": patch
---

On iOS, implement `application:openURL:options:` to handle custom URL schemes.
51 changes: 39 additions & 12 deletions src/platform_impl/ios/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,40 @@ pub fn create_delegate_class() {
YES
}

fn handle_deep_link(url: id) {
unsafe {
let absolute_url: id = msg_send![url, absoluteString];
let bytes = {
let bytes: *const c_char = msg_send![absolute_url, UTF8String];
bytes as *const u8
};

// 4 represents utf8 encoding
let len = msg_send![absolute_url, lengthOfBytesUsingEncoding: 4];
let bytes = std::slice::from_raw_parts(bytes, len);

let url = url::Url::parse(std::str::from_utf8(bytes).unwrap()).unwrap();

app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Opened { urls: vec![url] }));
}
}

// custom URL schemes
// https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app
extern "C" fn application_open_url(
_self: &mut Object,
_cmd: Sel,
_app: id,
url: id,
_options: id,
) -> BOOL {
handle_deep_link(url);

YES
}

// universal links
// https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app
extern "C" fn application_continue(
_: &mut Object,
_: Sel,
Expand All @@ -568,19 +601,8 @@ pub fn create_delegate_class() {
if webpage_url == nil {
return NO;
}
let absolute_url: id = msg_send![webpage_url, absoluteString];
let bytes = {
let bytes: *const c_char = msg_send![absolute_url, UTF8String];
bytes as *const u8
};

// 4 represents utf8 encoding
let len = msg_send![absolute_url, lengthOfBytesUsingEncoding: 4];
let bytes = std::slice::from_raw_parts(bytes, len);

let url = url::Url::parse(std::str::from_utf8(bytes).unwrap()).unwrap();

app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Opened { urls: vec![url] }));
handle_deep_link(webpage_url);

YES
}
Expand Down Expand Up @@ -631,6 +653,11 @@ pub fn create_delegate_class() {
did_finish_launching as extern "C" fn(&mut Object, Sel, id, id) -> BOOL,
);

decl.add_method(
sel!(application:openURL:options:),
application_open_url as extern "C" fn(&mut Object, Sel, id, id, id) -> BOOL,
);

decl.add_method(
sel!(application:continueUserActivity:restorationHandler:),
application_continue as extern "C" fn(&mut Object, Sel, id, id, id) -> BOOL,
Expand Down

0 comments on commit ad652e5

Please sign in to comment.