-
Notifications
You must be signed in to change notification settings - Fork 29.5k
Add deeplinking for UIScene migration #176303
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
Conversation
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.
Code Review
This pull request adds support for handling deeplinks in iOS apps that have migrated to UIScene, while maintaining compatibility with older apps. The changes involve refactoring deeplink handling logic by moving it from FlutterViewController and FlutterAppDelegate to FlutterEngine and FlutterSceneLifeCycle respectively. This centralization allows for deeplinks to be processed correctly through scene delegate events. The changes are well-tested, with new unit tests covering the added UIScene deeplinking paths and updated tests for the refactored code. My review includes a couple of suggestions for improving robustness and cleaning up debug code.
engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterSceneLifeCycle.mm
Outdated
Show resolved
Hide resolved
engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterSceneLifeCycle.mm
Show resolved
Hide resolved
LongCatIsLooong
left a comment
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.
LGTM. It looks like the reason that deeplinking implementation is called at the end is that it's always going to return YES if deeplinking is enabled?
| if (!FlutterSharedApplication.isFlutterDeepLinkingEnabled) { | ||
| return NO; | ||
| } | ||
| for (FlutterEngine* engine in _engines.allObjects) { |
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.
IIRC there's method you need to call before accessing the weak pointer array?
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.
Ah [self updateEnginesInScene:scene];
engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterSceneLifeCycle.mm
Outdated
Show resolved
Hide resolved
| // universal link to the scene(_:willConnectTo:options:) delegate method after launch, and to | ||
| // scene(_:continue:) when the universal link is tapped while your app is running or suspended in | ||
| // memory. | ||
| for (NSUserActivity* userActivity in connectionOptions.userActivities) { |
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.
Can user activities and URLContexts be both present in a connection option?
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.
Not that I'm aware of. userActivities handled universal links (when the link prefixed with http/https). URLContexts is when it's a non-standard scheme, such as my-custom-scheme://my-url.com. Both are a form of deeplinking
engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterSceneLifeCycle.mm
Outdated
Show resolved
Hide resolved
| [self updateEnginesInScene:scene]; | ||
|
|
||
| BOOL consumedByPlugin = NO; | ||
| for (FlutterEngine* engine in _engines.allObjects) { |
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.
Not directly related to this PR, but I thought at this point _engines should be an empty array since the scene has not connected yet so we don't know which views will be in this scene?
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 found away around that, see this comment: #175866 (comment)
| * @return `YES` if any plugin handles the request. | ||
| */ | ||
| - (BOOL)scene:(UIScene*)scene | ||
| - (void)scene:(UIScene*)scene |
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.
@LongCatIsLooong I changed these APIs in FlutterSceneLifeCycleProvider (protocol add-to-app devs can use instead of using FlutterSceneDelegate) to void because in UIKit they are void. I thought our application-equivalent returned BOOLs, however, I was mistaken in that it only retuned BOOLs for the ones UIKit did.
For example, application:continueUserActivity:restorationHandler: returns a BOOL because it also does in UIKit.
Lines 141 to 143 in 72eec03
| - (BOOL)application:(UIApplication*)application | |
| continueUserActivity:(NSUserActivity*)userActivity | |
| restorationHandler:(void (^)(NSArray*))restorationHandler; |
But application:performActionForShortcutItem:completionHandler: returns void because UIKit does
Lines 111 to 114 in 72eec03
| - (void)application:(UIApplication*)application | |
| performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem | |
| completionHandler:(void (^)(BOOL succeeded))completionHandler | |
| API_AVAILABLE(ios(9.0)); |
UIKit returns void for all of the scene events
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.
FlutterPluginAppLifeCycleDelegate (the protocol plugins conform to) and FlutterEnginePluginSceneLifeCycleDelegate (internal API that forwards events to plugin) still uses BOOLs so we can track that we only allow one plugin to process
|
|
||
| - (void)sendDeepLinkToFramework:(NSURL*)url completionHandler:(void (^)(BOOL success))completion { | ||
| __weak FlutterEngine* weakSelf = self; | ||
| [self waitForFirstFrame:3.0 |
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.
We need this due to the existing behavior that iOS deeplink will first launch the app and then a random delay later it will sends a [UIApplication openUrl]. that is why we need a delay to wait for first frame. Is this still the case for UIScene?
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.
Yes, we still need the delay
…10170) Manual roll requested by tarrinneal@google.com flutter/flutter@65aca36...5c0c9e9 2025-10-03 engine-flutter-autoroll@skia.org Roll Packages from 5fd5f74 to e401aeb (4 revisions) (flutter/flutter#176466) 2025-10-03 engine-flutter-autoroll@skia.org Roll Dart SDK from fdd90f38d6a0 to 0009748aed50 (3 revisions) (flutter/flutter#176461) 2025-10-03 engine-flutter-autoroll@skia.org Roll Skia from f86ae4113254 to b842026480e0 (3 revisions) (flutter/flutter#176458) 2025-10-03 engine-flutter-autoroll@skia.org Roll Skia from 1720a85a507e to f86ae4113254 (1 revision) (flutter/flutter#176443) 2025-10-03 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from Vnoygds8HtDUvGLCK... to HUhTcRn-LUXa2Salu... (flutter/flutter#176442) 2025-10-03 engine-flutter-autoroll@skia.org Roll Skia from cf339ab390c2 to 1720a85a507e (4 revisions) (flutter/flutter#176439) 2025-10-03 engine-flutter-autoroll@skia.org Roll Dart SDK from 4f90a06328cb to fdd90f38d6a0 (7 revisions) (flutter/flutter#176431) 2025-10-02 engine-flutter-autoroll@skia.org Roll Skia from 05c1f5803415 to cf339ab390c2 (11 revisions) (flutter/flutter#176426) 2025-10-02 15619084+vashworth@users.noreply.github.com Add deeplinking for UIScene migration (flutter/flutter#176303) 2025-10-02 vegorov@google.com Upgrade packages (flutter/flutter#176411) 2025-10-02 36861262+QuncCccccc@users.noreply.github.com Update localization from translation console (flutter/flutter#176324) 2025-10-02 jessiewong401@gmail.com Update Framework CI to Use NDK r28c (flutter/flutter#176214) 2025-10-02 fishythefish@users.noreply.github.com Remove references to dart:js_util (flutter/flutter#176323) 2025-10-02 engine-flutter-autoroll@skia.org Roll Packages from 321a584 to 5fd5f74 (6 revisions) (flutter/flutter#176409) 2025-10-02 matt.kosarek@canonical.com Windowing integration tests now await change futures if a changes is expected + commenting our erroneous icon in Runner.rc for win32 (flutter/flutter#176312) 2025-10-02 katelovett@google.com Fix platform specific semantics for time picker buttons (flutter/flutter#176373) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC stuartmorgan@google.com,tarrinneal@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
When an iOS app migrates to UIScene, the application events for handling deeplinks are no longer called by UIKit. Instead, scene events in the SceneDelegate must be used. This PR adds support for handling deeplinks in UIScene while still maintaining support for unmigrated apps, as well. Fixes flutter#174403. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
When an iOS app migrates to UIScene, the application events for handling deeplinks are no longer called by UIKit. Instead, scene events in the SceneDelegate must be used. This PR adds support for handling deeplinks in UIScene while still maintaining support for unmigrated apps, as well. Fixes flutter#174403. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
When an iOS app migrates to UIScene, the application events for handling deeplinks are no longer called by UIKit. Instead, scene events in the SceneDelegate must be used. This PR adds support for handling deeplinks in UIScene while still maintaining support for unmigrated apps, as well.
Fixes #174403.
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.