React Native 0.66升级后iOS初始化RCTRootView启动崩溃问题求助
React Native 0.63升级0.66启动崩溃问题解决
问题现象
将React Native项目从0.63版本升级到0.66版本,调试模式构建后App启动阶段崩溃,报错信息为uncaught exception 'NSInvalidArgumentException', reason: '-[REAEventDispatcher setBridge:]: unrecognized selector sent to instance 0x600002f51cc0',崩溃点位于AppDelegate.m文件初始化RCTRootView的步骤。
参考代码
AppDelegate.m
#import "AppDelegate.h" #import <React/RCTBridge.h> #import <React/RCTBundleURLProvider.h> #import <React/RCTRootView.h> #import <React/RCTLinkingManager.h> #import "RNBootSplash.h" #import <GoogleMaps/GoogleMaps.h> #import <UserNotifications/UserNotifications.h> #import <RNCPushNotificationIOS.h> #import <Firebase.h> #ifdef FB_SONARKIT_ENABLED #import <FlipperKit/FlipperClient.h> #import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h> #import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h> #import <FlipperKitReactPlugin/FlipperKitReactPlugin.h> #import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h> #import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h> static void InitializeFlipper(UIApplication *application) { FlipperClient *client = [FlipperClient sharedClient]; SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; [client addPlugin:[FlipperKitReactPlugin new]]; [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; [client start]; } #endif @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if([FIRApp defaultApp] == nil){ [FIRApp configure]; } [GMSServices provideAPIKey:@"AIzaSyC-BV0Dp46BQ1iP1HRws-oP_90FV0Aewfo"]; // add this line using the api key obtained from Google Console #ifdef FB_SONARKIT_ENABLED InitializeFlipper(application); #endif RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions] //应用崩溃位置 RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Flatz" initialProperties:nil]; if (@available(iOS 13.0, *)) { rootView.backgroundColor = [UIColor systemBackgroundColor]; } else { rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; } self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [UIViewController new]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; [RNBootSplash initWithStoryboard:@"LaunchScreen" rootView:rootView]; // < - initialization using the storyboard file name // Define UNUserNotificationCenter UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; return YES; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #ifdef FB_SONARKIT_ENABLED return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } // Required for the register event. - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; } // Required for the notification event. You must call the completion handler after handling the remote notification. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; } // Required for the registrationError event. - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error]; } // Required for localNotification event - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { [RNCPushNotificationIOS didReceiveNotificationResponse:response]; } //Called when a notification is delivered to a foreground app. -(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler { completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge); } - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { return [RCTLinkingManager application:application openURL:url options:options]; } - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler { return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; } @end
Podfile
require_relative '../node_modules/react-native/scripts/react_native_pods' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' platform :ios, '11.0' target 'Flatz' do # No individual tracking of people or their phones $RNFirebaseAnalyticsWithoutAdIdSupport=true # React Native Maps dependencies rn_maps_path = '../node_modules/react-native-maps' pod 'react-native-google-maps', :path => rn_maps_path pod 'GoogleMaps' pod 'Google-Maps-iOS-Utils' config = use_native_modules! use_react_native!( :path => config["reactNativePath"], :hermes_enabled => true ) target 'FlatzTests' do inherit! :complete # Pods for testing end # Enables Flipper. # # Note that if you have use_frameworks! enabled, Flipper will not work and # you should disable these next few lines. use_flipper!({ 'Flipper-Folly' => '2.5.3', 'Flipper' => '0.87.0', 'Flipper-RSocket' => '1.3.1' }) post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| #1 deployment_target = config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] #2 target_components = deployment_target.split #3 if target_components.length > 0 #4 target_initial = target_components[0].to_i #5 if target_initial < 9 config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = "9.0" end end end end installer.pods_project.build_configurations.each do |config| config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" end end permissions_path = '../node_modules/react-native-permissions/ios' pod 'Permission-Camera', :path => "#{permissions_path}/Camera" end
问题原因
报错前缀REA对应react-native-reanimated动画库,RN 0.64+版本已经废弃了原生模块的setBridge:旧接口,你项目中的reanimated版本是适配RN 0.63的旧版本,调用了已被移除的接口就会触发unrecognized selector崩溃。
解决步骤
- 升级react-native-reanimated到适配RN 0.66的版本,推荐升级到2.2.x及以上的2.x稳定版本,不要直接跨大版本升级到3.x避免产生其他兼容问题
- 升级完成后按顺序执行以下操作清理缓存重新构建:
- 删除项目根目录的node_modules文件夹,重新执行
npm install或者yarn install安装依赖 - 进入ios目录,删除Podfile.lock文件和Pods文件夹
- 执行
pod install --repo-update重新安装iOS依赖 - 打开Xcode执行Product -> Clean Build Folder清理构建缓存后重新运行项目
- 删除项目根目录的node_modules文件夹,重新执行
- 若升级后仍有异常,检查babel.config.js中是否正确配置了reanimated的插件:
module.exports = { plugins: [ 'react-native-reanimated/plugin', ], };
内容的提问来源于stack exchange,提问作者evegul
相关产品推荐
相关产品推荐

