You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何重构AppDelegate.m避免react-native-splash-screen致iOS端JS重复加载

Fix: JavaScript Executes Twice with react-native-splash-screen on iOS

I've run into this exact issue before with newer React Native versions—here's what's happening and how to fix it:

Root Cause

The default iOS implementation of react-native-splash-screen creates a separate UIWindow to display the splash screen. In newer React Native releases, this can interfere with the main app window's lifecycle, triggering a re-mount of the React root view and thus running your JavaScript initialization code twice. This breaks logic like deep link/notification detection, since the second load won't have access to the initial launch options.

Solution 1: Modify react-native-splash-screen's Native Code

Instead of creating a new window for the splash screen, we'll attach it directly to the app's main root view controller. Here's how:

  1. Open ios/RNSplashScreen.m from the library (you can find this in your project's Pods directory if using CocoaPods).
  2. Locate the + (void)show method and replace it with this:
    + (void)show {
        UIWindow *mainWindow = [UIApplication sharedApplication].keyWindow ?: [[UIApplication sharedApplication].windows firstObject];
        [self show:@"LaunchScreen" inRootView:mainWindow.rootViewController.view];
    }
    
  3. Keep the rest of the library code intact. This forces the splash screen to render within your app's existing window instead of spawning a new one, eliminating the duplicate JS load.

Solution 2: Adjust AppDelegate Initialization Flow

If you prefer not to modify the library code, you can restructure your AppDelegate.m to load React asynchronously after showing a custom splash screen:

Replace your didFinishLaunchingWithOptions method with this:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
#ifdef FB_SONARKIT_ENABLED
  InitializeFlipper(application);
#endif
  
  [GMSServices provideAPIKey:@"[redacted]"];
  
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }

  // Step 1: Set up window and show splash screen first
  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *splashVC = [UIViewController new];
  
  // Load your launch screen image (match your LaunchScreen.storyboard assets)
  UIImageView *splashImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"LaunchScreen"]];
  splashImageView.frame = self.window.bounds;
  splashImageView.contentMode = UIViewContentModeScaleAspectFill;
  [splashVC.view addSubview:splashImageView];
  
  self.window.rootViewController = splashVC;
  [self.window makeKeyAndVisible];

  // Step 2: Initialize React bridge asynchronously
  __weak typeof(self) weakSelf = self;
  self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  
  // Wait for bridge to load before showing React view
  dispatch_async(dispatch_get_main_queue(), ^{
    RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:weakSelf.bridge moduleName:@"PartyMe" initialProperties:nil];
    rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
    
    UIViewController *reactVC = [UIViewController new];
    reactVC.view = rootView;
    
    // Switch to React view without animation
    [weakSelf.window.rootViewController presentViewController:reactVC animated:NO completion:^{
      weakSelf.window.rootViewController = reactVC;
    }];
  });

  return YES;
}

Then, in your React code, you can still use SplashScreen.hide() once your app is ready—just make sure to import the library as usual.

Verify the Fix

After making either change, run your app and check your JavaScript logs. You should only see your initialization code execute once, and notification/deep link detection should work as expected since the launch options are preserved for the single JS load.

内容的提问来源于stack exchange,提问作者Tristan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:26:57