React Native iOS添加SceneDelegate后冷启动DeepLink无法跳转
React Native冷启动DeepLink失效(SceneDelegate+CarPlay场景)解决方案
问题根源
iOS 13+引入SceneDelegate后,App冷启动时的DeepLink参数不再通过AppDelegate的application:openURL:options:或application:continueUserActivity:restorationHandler:传递,而是直接传到SceneDelegate的scene:willConnectToSession:options:方法中。后台唤醒时AppDelegate的原有逻辑仍会触发,但冷启动时只有SceneDelegate能拿到跳转参数,没处理这部分就会导致只启动App、无法跳转目标页面的问题。
修复步骤
1. 在SceneDelegate中处理冷启动参数
修改SceneDelegate.m(或Swift版本的SceneDelegate.swift),在scene:willConnectToSession:options:方法里提取DeepLink的URL或UserActivity,复用你原本在AppDelegate中的DeepLink处理逻辑。
Objective-C示例代码:
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { // 处理URL Scheme类型的DeepLink if (connectionOptions.URLContexts.count > 0) { NSURL *url = [[connectionOptions.URLContexts allObjects][0] URL]; [self handleDeepLink:url]; } // 处理Universal Link类型的DeepLink if (connectionOptions.userActivity) { [self continueUserActivity:connectionOptions.userActivity]; } // 保留React Native原有初始化代码 UIWindow *window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene]; self.window = window; RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"YourAppName" initialProperties:nil]; rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; self.window.rootViewController = [[UIViewController alloc] init]; self.window.rootViewController.view = rootView; [self.window makeKeyAndVisible]; } // 复用AppDelegate中的DeepLink处理逻辑 - (void)handleDeepLink:(NSURL *)url { RCTBridge *bridge = [RCTBridge currentBridge]; if (bridge) { // 通过RN的事件发射器把URL传给JS层处理 [bridge enqueueJSCall:@"RCTDeviceEventEmitter" method:@"emit" args:@[@"deepLinkReceived", url.absoluteString]]; } } - (BOOL)continueUserActivity:(NSUserActivity *)userActivity { if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { NSURL *url = userActivity.webpageURL; [self handleDeepLink:url]; return YES; } return NO; }
2. 优化AppDelegate的兼容逻辑
保留AppDelegate中后台唤醒时的DeepLink处理,同时把核心处理逻辑抽成公共方法,方便SceneDelegate复用,避免代码冗余:
// AppDelegate.m - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { [self handleDeepLink:url]; return YES; } - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler { return [self continueUserActivity:userActivity]; } // 公共处理方法,和SceneDelegate中的保持一致 - (void)handleDeepLink:(NSURL *)url { RCTBridge *bridge = [RCTBridge currentBridge]; if (bridge) { [bridge enqueueJSCall:@"RCTDeviceEventEmitter" method:@"emit" args:@[@"deepLinkReceived", url.absoluteString]]; } } - (BOOL)continueUserActivity:(NSUserActivity *)userActivity { if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { NSURL *url = userActivity.webpageURL; [self handleDeepLink:url]; return YES; } return NO; }
3. 验证Info.plist配置
确保Info.plist中同时满足Scene和DeepLink的配置要求:
- 确认
UIApplicationSceneManifest下的UISceneConfigurations包含CarPlay场景(CPTemplateApplicationSceneSessionRoleApplication)和普通手机场景(UIWindowSceneSessionRoleApplication)的配置 - 确认
CFBundleURLTypes(URL Scheme)或NSUserActivityTypes(Universal Link)的配置正确,和你使用的DeepLink规则匹配
额外注意事项
- 如果你用React Navigation做页面导航,需要在JS层监听
deepLinkReceived事件,或者配置NavigationContainer的deepLink属性,确保收到URL后能正确路由到目标页面。 - 测试时必须完全杀死App(从多任务列表划掉),再点击DeepLink测试冷启动场景,避免后台唤醒的情况干扰测试结果。
内容的提问来源于stack exchange,提问作者Sagar
相关产品推荐
相关产品推荐

