fix(iOS): drain UISceneConnectionOptions on cold launch (#21362)#21394
Merged
MrJul merged 1 commit intoMay 19, 2026
Merged
Conversation
…1362) When the iOS app uses scene-based lifecycle (iOS 13+), Apple delivers cold-launch user activities and URL contexts via UISceneConnectionOptions on scene:willConnectToSession:options: — NOT via the warm-path selectors scene:continueUserActivity: or scene:openURLContexts:. AvaloniaSceneDelegate ignored connectionOptions entirely, so cold-launching the app from a Universal Link or custom-scheme URL dropped the URL on the floor. The user's subscriber to IActivatableLifetime.Activated then only saw the base ActivatedEventArgs raised by the foreground transition (OnLeavingBackground), never a ProtocolActivatedEventArgs with the URL. Fix: in WillConnect, after the window is created and made key, drain both connectionOptions.UserActivities and connectionOptions.UrlContexts through the existing IAvaloniaAppInternalDelegate paths. Also add a scene:openURLContexts: handler so warm custom-scheme URLs work under scene lifecycle (previously these were silently dropped too — application:openURL: on the AppDelegate is not called when scenes are in use). Closes AvaloniaUI#21362 (cold path of AvaloniaUI#17600 / AvaloniaUI#18005). The IAvaloniaAppInternalDelegate interface gains an OpenUrl(NSUrl) method so the scene delegate can route URL contexts through the same code path the existing application:openURL:options: AppDelegate handler uses. No new tests — the Avalonia.iOS UnitTests and IntegrationTests projects don't currently exist in the repo. Manual verification steps in the issue: build any Avalonia.iOS app with Associated Domains entitlement + AASA served, force-quit, tap a Universal Link, observe the Activated event fires with ProtocolActivatedEventArgs (not base ActivatedEventArgs). Happy to add a test if maintainers can point at a scene-lifecycle test fixture to model from.
|
You can test this PR using the following package version. |
Collaborator
|
Contributor
Author
|
@cla-avalonia agree |
Contributor
Author
MrJul
approved these changes
May 19, 2026
MrJul
pushed a commit
to MrJul/Avalonia
that referenced
this pull request
May 28, 2026
…1362) (AvaloniaUI#21394) When the iOS app uses scene-based lifecycle (iOS 13+), Apple delivers cold-launch user activities and URL contexts via UISceneConnectionOptions on scene:willConnectToSession:options: — NOT via the warm-path selectors scene:continueUserActivity: or scene:openURLContexts:. AvaloniaSceneDelegate ignored connectionOptions entirely, so cold-launching the app from a Universal Link or custom-scheme URL dropped the URL on the floor. The user's subscriber to IActivatableLifetime.Activated then only saw the base ActivatedEventArgs raised by the foreground transition (OnLeavingBackground), never a ProtocolActivatedEventArgs with the URL. Fix: in WillConnect, after the window is created and made key, drain both connectionOptions.UserActivities and connectionOptions.UrlContexts through the existing IAvaloniaAppInternalDelegate paths. Also add a scene:openURLContexts: handler so warm custom-scheme URLs work under scene lifecycle (previously these were silently dropped too — application:openURL: on the AppDelegate is not called when scenes are in use). Closes AvaloniaUI#21362 (cold path of AvaloniaUI#17600 / AvaloniaUI#18005). The IAvaloniaAppInternalDelegate interface gains an OpenUrl(NSUrl) method so the scene delegate can route URL contexts through the same code path the existing application:openURL:options: AppDelegate handler uses. No new tests — the Avalonia.iOS UnitTests and IntegrationTests projects don't currently exist in the repo. Manual verification steps in the issue: build any Avalonia.iOS app with Associated Domains entitlement + AASA served, force-quit, tap a Universal Link, observe the Activated event fires with ProtocolActivatedEventArgs (not base ActivatedEventArgs). Happy to add a test if maintainers can point at a scene-lifecycle test fixture to model from.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #21362 — the cold-launch path of #17600 (#18005 only addressed the warm path).
When the iOS app uses scene-based lifecycle (iOS 13+), Apple delivers cold-launch user activities and URL contexts via
UISceneConnectionOptionsonscene:willConnectToSession:options:— not via the warm-path selectorsscene:continueUserActivity:orscene:openURLContexts:.AvaloniaSceneDelegateignoredconnectionOptionsentirely, so cold-launching the app from a Universal Link or custom-scheme URL dropped the URL on the floor.The user's subscriber to
IActivatableLifetime.Activatedthen only saw the baseActivatedEventArgsraised by the foreground transition (OnLeavingBackground), never aProtocolActivatedEventArgswith the URL.Change
AvaloniaSceneDelegate.WillConnect, after creating the window, drains bothconnectionOptions.UserActivitiesandconnectionOptions.UrlContextsthrough the existingIAvaloniaAppInternalDelegatepaths.Also adds
scene:openURLContexts:so warm custom-scheme URLs work under scene lifecycle — previously these were silently dropped too becauseapplication:openURL:on the AppDelegate is not called when scenes are in use (a smaller pre-existing bug surfaced by this same investigation).The
IAvaloniaAppInternalDelegateinterface gains anOpenUrl(NSUrl)method so the scene delegate can route URL contexts through the same code path the existingapplication:openURL:options:AppDelegate handler uses. The AppDelegate's publicOpenUrlselector method is refactored to a one-liner delegating to the explicit interface impl — no behaviour change for the AppDelegate-only path.Test plan
The
Avalonia.iOS.UnitTests/Avalonia.IntegrationTests.iOSpaths in sparse-checkout return empty, so iOS scene-lifecycle test scaffolding doesn't currently exist in the repo to model from. Happy to add a test if maintainers can point at a fixture pattern.Manual repro (from issue):
Associated Domainsentitlement (applinks:<your-domain>) + matching AASA served.IActivatableLifetime.ActivatedinApp.Initialize, logProtocolActivatedEventArgs.Kindvs the bare type name.https://<your-domain>/...Universal Link from Messages / Mail.Activatedfires with baseActivatedEventArgs, no URL surfaces. Device console:OnActivated fired: kind=ActivatedEventArgs.Activatedfires withProtocolActivatedEventArgs.Kind == OpenUricarrying the URL.For URL contexts (custom schemes via scene lifecycle): same flow, with a
myapp://...URL instead of a Universal Link — before this PR these fall through entirely under scene lifecycle; after, they route toProtocolActivatedEventArgslike the AppDelegate path.References
🤖 PR drafted with assistance from Claude Code