Skip to content

Commit

Permalink
feat(iOS): added custom URL schemes handling in the AppDelegate class
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
CampioneDev committed Aug 30, 2024
1 parent 9b5aa60 commit 7155955
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 12 deletions.
35 changes: 35 additions & 0 deletions .changes/ios-custom-url-schemes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
"tao": patch
---

# 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.
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 7155955

Please sign in to comment.