这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@vashworth
Copy link
Contributor

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

@vashworth vashworth requested a review from a team as a code owner September 30, 2025 18:13
@github-actions github-actions bot added platform-ios iOS applications specifically engine flutter/engine related. See also e: labels. team-ios Owned by iOS platform team labels Sep 30, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a 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.

Copy link
Contributor

@LongCatIsLooong LongCatIsLooong left a 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) {
Copy link
Contributor

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?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah [self updateEnginesInScene:scene];

// 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) {
Copy link
Contributor

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?

Copy link
Contributor Author

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

[self updateEnginesInScene:scene];

BOOL consumedByPlugin = NO;
for (FlutterEngine* engine in _engines.allObjects) {
Copy link
Contributor

@LongCatIsLooong LongCatIsLooong Sep 30, 2025

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?

Copy link
Contributor Author

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
Copy link
Contributor Author

@vashworth vashworth Oct 1, 2025

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.

- (BOOL)application:(UIApplication*)application
continueUserActivity:(NSUserActivity*)userActivity
restorationHandler:(void (^)(NSArray*))restorationHandler;

https://developer.apple.com/documentation/uikit/uiapplicationdelegate/application(_:continue:restorationhandler:)?language=objc

But application:performActionForShortcutItem:completionHandler: returns void because UIKit does

- (void)application:(UIApplication*)application
performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
completionHandler:(void (^)(BOOL succeeded))completionHandler
API_AVAILABLE(ios(9.0));

https://developer.apple.com/documentation/uikit/uiapplicationdelegate/application(_:performactionfor:completionhandler:)?language=objc

UIKit returns void for all of the scene events

Copy link
Contributor Author

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
Copy link
Contributor

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?

Copy link
Contributor Author

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

@vashworth vashworth added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 2, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Oct 2, 2025
Merged via the queue into flutter:master with commit 7677608 Oct 2, 2025
188 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 2, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 3, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 3, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 3, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 3, 2025
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Oct 3, 2025
…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
mboetger pushed a commit to mboetger/flutter that referenced this pull request Oct 7, 2025
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
okorohelijah pushed a commit to okorohelijah/flutter that referenced this pull request Oct 7, 2025
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
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

engine flutter/engine related. See also e: labels. platform-ios iOS applications specifically team-ios Owned by iOS platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[UIScene] Migrate Deep Linking / Universal Links for scenes

3 participants