-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[deep link][ios] Update openURL method to reflect the result from framework #52643
Changes from all commits
0d37280
ebcebc3
1c0b1ae
efb8d7f
4bc49e9
84c455c
9f5dc68
6c5334b
acf89e3
6a750af
bbd7271
14a3864
d54846f
5cba4ff
f8c981e
73df547
bbb545a
dd3fab6
c88757a
30088a9
590eedd
2e916d8
a69612b
8983622
a277951
8207b3e
0a43d07
8136379
5c5b591
0ea42e9
e5450fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -134,44 +134,47 @@ - (void)userNotificationCenter:(UNUserNotificationCenter*)center | |
} | ||
} | ||
|
||
- (BOOL)openURL:(NSURL*)url { | ||
- (BOOL)isFlutterDeepLinkingEnabled { | ||
NSNumber* isDeepLinkingEnabled = | ||
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"]; | ||
if (!isDeepLinkingEnabled.boolValue) { | ||
// Not set or NO. | ||
return NO; | ||
} else { | ||
FlutterViewController* flutterViewController = [self rootFlutterViewController]; | ||
if (flutterViewController) { | ||
[flutterViewController.engine | ||
waitForFirstFrame:3.0 | ||
callback:^(BOOL didTimeout) { | ||
if (didTimeout) { | ||
FML_LOG(ERROR) | ||
<< "Timeout waiting for the first frame when launching an URL."; | ||
} else { | ||
[flutterViewController.engine.navigationChannel | ||
invokeMethod:@"pushRouteInformation" | ||
arguments:@{ | ||
@"location" : url.absoluteString ?: [NSNull null], | ||
}]; | ||
} | ||
}]; | ||
return YES; | ||
} else { | ||
FML_LOG(ERROR) << "Attempting to open an URL without a Flutter RootViewController."; | ||
return NO; | ||
} | ||
} | ||
// if not set, return NO | ||
return isDeepLinkingEnabled ? [isDeepLinkingEnabled boolValue] : NO; | ||
} | ||
|
||
// This method is called when opening an URL with custom schemes. | ||
hangyujin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- (BOOL)application:(UIApplication*)application | ||
openURL:(NSURL*)url | ||
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options { | ||
if ([_lifeCycleDelegate application:application openURL:url options:options]) { | ||
return YES; | ||
} | ||
return [self openURL:url]; | ||
|
||
// Relaying to the system here will case an infinite loop, so we don't do it here. | ||
return [self handleOpenURL:url options:options relayToSystemIfUnhandled:NO]; | ||
} | ||
|
||
// Helper function for opening an URL, either with a custom scheme or a http/https scheme. | ||
- (BOOL)handleOpenURL:(NSURL*)url | ||
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options | ||
relayToSystemIfUnhandled:(BOOL)throwBack { | ||
if (![self isFlutterDeepLinkingEnabled]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we still ned this check if we go delegate to other selector in line 194? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just add this so the return value reflect the value of the flag. |
||
return NO; | ||
} | ||
|
||
FlutterViewController* flutterViewController = [self rootFlutterViewController]; | ||
if (flutterViewController) { | ||
[flutterViewController sendDeepLinkToFramework:url | ||
completionHandler:^(BOOL success) { | ||
if (!success && throwBack) { | ||
// throw it back to iOS | ||
[UIApplication.sharedApplication openURL:url]; | ||
} | ||
}]; | ||
} else { | ||
FML_LOG(ERROR) << "Attempting to open an URL without a Flutter RootViewController."; | ||
return NO; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: If you are iffy about using BOOL flag for completeness, a semaphore version can be (pseudocode):
Though a BOOL flag would be equally as good, since callback happens on main thread. I don't have a preference here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I just saw @jmagman's comment on semaphore. To use semaphore on the same thread, you can't block it due to deadlock, as jenn previously commented. Instead, you pass in |
||
return YES; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can this method get the result from completion handler only? Also is implementing this selector optional if we already implement the one with completionhandler? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can this method get the result from completion handler only?>> this application:openURL:options: method is non-async, i don't think its return value can be set from the completion handler so i used the deep link flag value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But should this method return before the completion handler is complete? Before, this method didn't return until There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what's the best practice to "spin the runloop"? I updated the code to wait for the completion handler but got failures : Failures for clang-tidy on /Volumes/Work/s/w/ir/cache/builder/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm: |
||
} | ||
|
||
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url { | ||
|
@@ -204,6 +207,7 @@ - (void)application:(UIApplication*)application | |
completionHandler:completionHandler]; | ||
} | ||
|
||
// This method is called when opening an URL with a http/https scheme. | ||
- (BOOL)application:(UIApplication*)application | ||
continueUserActivity:(NSUserActivity*)userActivity | ||
restorationHandler: | ||
|
@@ -214,7 +218,8 @@ - (BOOL)application:(UIApplication*)application | |
restorationHandler:restorationHandler]) { | ||
return YES; | ||
} | ||
return [self openURL:userActivity.webpageURL]; | ||
|
||
return [self handleOpenURL:userActivity.webpageURL options:@{} relayToSystemIfUnhandled:YES]; | ||
} | ||
|
||
#pragma mark - FlutterPluginRegistry methods. All delegating to the rootViewController | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this can be just
isDeepLinkingEnabled.boolValue
since sending message to nil will returnNO
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will keep this and flip NO to YES in #52350