Deep and Universal Links currently do not work on RN visionOS. Since iOS 13, if the project has opted into Scenes, lifecycle events are now controlled by SceneDelegate instead of AppDelegate.
After this PR is merged, we also need docs showing how to implement them, since the React Native docs only apply to non-Scene apps.
This PR is intended to be worked on. Currently, this solution works for Deep and Universal links when the app is already running or in background. When launching the app (previously killed) via Deep or Universal Links, Linking.getInitialUrl() will always return null, due to launchOptions being initialized as an empty object in RCTReactViewController.
class SceneDelegate: NSObject, UIWindowSceneDelegate {
...
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Other logic already present here
...
// Deep Links and Universal Links - called when the app was previously NOT running
RCTLinkingManager.scene(scene, willConnectTo: session, options: connectionOptions)
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
// Deep Links - called when the app was previously running or suspended
RCTLinkingManager.scene(scene, openURLContexts: URLContexts)
}
}
App.swift
struct visionaryApp: App {
@UIApplicationDelegateAdaptor var delegate: AppDelegate
var body: some Scene {
WindowGroup {
TabView {
RCTRootViewRepresentable(moduleName: "myApp")
.tabItem {
Label("Home", systemImage: "house.fill")
}
RCTRootViewRepresentable(moduleName: "SettingsScreen")
.tabItem {
Label("Settings", systemImage: "gear")
}
}
// Add the onOpenURL view modifier
// Calling AppDelegate directly here but this should be improved to call SceneDelegate, probably
.onOpenURL(perform: { (universalLink: URL) in
delegate.onOpenURL(url: universalLink)
})
}
}
}
AppDelegate.swift
class AppDelegate: RCTAppDelegate {
...
// Universal Links - called when the app was previously running or suspended
func onOpenURL(url: URL) {
RCTLinkingManager.onOpen(url)
}
}
Changelog:
[IOS] [ADDED] - Added equivalent scene method scene:willConnectTo:options: to handle Deep and Universal Links when app was previously NOT running
[IOS] [ADDED] - Added equivalent scene method scene:openURLContexts: to handle Deep Links when app was previously in background or suspended
[IOS] [ADDED] - Added equivalent scene method onOpenURL to handle Universal Links when app was previously in background or suspended
Test Plan:
Deep Link (rntester://) with app previously killed, fetch initial URL via Linking.getInitialURL()
Deep Link (rntester://) with app previously running or suspended, fetch incoming url via Linking.addEventListener('url', callback)
Universal Link with app previously killed, fetch initial URL via Linking.getInitialURL()
Universal Link with app previously running or suspended, fetch incoming url via Linking.addEventListener('url', callback)
Summary:
Fixes #138
Deep and Universal Links currently do not work on RN visionOS. Since iOS 13, if the project has opted into Scenes, lifecycle events are now controlled by SceneDelegate instead of AppDelegate.
After this PR is merged, we also need docs showing how to implement them, since the React Native docs only apply to non-Scene apps.
This PR is intended to be worked on. Currently, this solution works for Deep and Universal links when the app is already running or in background. When launching the app (previously killed) via Deep or Universal Links,
Linking.getInitialUrl()
will always returnnull
, due tolaunchOptions
being initialized as an empty object inRCTReactViewController
.The Apple Documentation indicates
scene(_ :continue:)
for handling Universal Links when app is already running, but that only applies to UIKit-based apps. For SwiftUI, theonOpenURL(_:perform:)
view modifier must be used.Final usage example for apps:
SceneDelegate.swift
App.swift
AppDelegate.swift
Changelog:
[IOS] [ADDED] - Added equivalent scene method
scene:willConnectTo:options:
to handle Deep and Universal Links when app was previously NOT running [IOS] [ADDED] - Added equivalent scene methodscene:openURLContexts:
to handle Deep Links when app was previously in background or suspended [IOS] [ADDED] - Added equivalent scene methodonOpenURL
to handle Universal Links when app was previously in background or suspendedTest Plan:
rntester://
) with app previously killed, fetch initial URL viaLinking.getInitialURL()
rntester://
) with app previously running or suspended, fetch incoming url viaLinking.addEventListener('url', callback)
Linking.getInitialURL()
Linking.addEventListener('url', callback)