React-native-splash-screen: Splash screen appears below JS content when using react native navigation

Created on 12 Feb 2020  路  5Comments  路  Source: crazycodeboy/react-native-splash-screen

I started using [RNSplashScreen showSplash]; and it was working great, however, I didn't know that this method is blocking the thread with a while loop. This caused for some listeners and callbacks (for example, branch) to not be called only after hiding the splash screen.

After understanding this, I started using [RNSplashScreen showSplash:@"LaunchScreen" inRootView:rootView];. However, it appeared for a second but when setting the rootScreen using RNN it disappeared because the JS content appears on top of it.

In order to fix it, I did this:

_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
_window.backgroundColor = [UIColor clearColor];
_window.userInteractionEnabled = NO;
_window.rootViewController = rootViewController;
rootViewController.view.userInteractionEnabled = NO;

[RNSplashScreen showSplash:@"LaunchScreen" inRootView: rootViewController.view];

[_window setHidden:NO];

And now I see the splash screen until using hide();.

Most helpful comment

Yes I created a new ui view controller.

Here is my full code

// The only way to show the splash screen over the JS ui and without blocking the thread
  rootViewController = [UIViewController new];

  _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  _window.backgroundColor = [UIColor clearColor];
  _window.userInteractionEnabled = NO;
  _window.rootViewController = rootViewController;
  rootViewController.view.userInteractionEnabled = NO;

  [RNSplashScreen showSplash:@"LaunchScreen" inRootView: rootViewController.view];

  [_window setHidden:NO];

  t = [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: @selector(onHideSplashScreen) userInfo: nil repeats:YES];

  return YES;
- (void)onHideSplashScreen  {
  // I want to die for implementing this like that, but I don't have a choice right now :(
  if (rootViewController.view.subviews.count == 0) {
    [t invalidate];
    t = nil;
    [[[UIApplication sharedApplication] delegate] setWindow:mainWindow];
  }
}

and the LaunchScreen in this case is a xib that looks the same as the LunchScreen.storyboard I set up in the settings of the project

All 5 comments

Hi @Rotemy I'm trying your solution in RNN but it doesn't work. How did you get the rootViewController from RNN? Or is it something like this? UIViewController *rootViewController = [UIViewController new]; BTW the "LaunchScreen" in your solutions is the xib file right?

Yes I created a new ui view controller.

Here is my full code

// The only way to show the splash screen over the JS ui and without blocking the thread
  rootViewController = [UIViewController new];

  _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  _window.backgroundColor = [UIColor clearColor];
  _window.userInteractionEnabled = NO;
  _window.rootViewController = rootViewController;
  rootViewController.view.userInteractionEnabled = NO;

  [RNSplashScreen showSplash:@"LaunchScreen" inRootView: rootViewController.view];

  [_window setHidden:NO];

  t = [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: @selector(onHideSplashScreen) userInfo: nil repeats:YES];

  return YES;
- (void)onHideSplashScreen  {
  // I want to die for implementing this like that, but I don't have a choice right now :(
  if (rootViewController.view.subviews.count == 0) {
    [t invalidate];
    t = nil;
    [[[UIApplication sharedApplication] delegate] setWindow:mainWindow];
  }
}

and the LaunchScreen in this case is a xib that looks the same as the LunchScreen.storyboard I set up in the settings of the project

Yes I created a new ui view controller.

Here is my full code

// The only way to show the splash screen over the JS ui and without blocking the thread
  rootViewController = [UIViewController new];

  _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  _window.backgroundColor = [UIColor clearColor];
  _window.userInteractionEnabled = NO;
  _window.rootViewController = rootViewController;
  rootViewController.view.userInteractionEnabled = NO;

  [RNSplashScreen showSplash:@"LaunchScreen" inRootView: rootViewController.view];

  [_window setHidden:NO];

  t = [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: @selector(onHideSplashScreen) userInfo: nil repeats:YES];

  return YES;
- (void)onHideSplashScreen  {
  // I want to die for implementing this like that, but I don't have a choice right now :(
  if (rootViewController.view.subviews.count == 0) {
    [t invalidate];
    t = nil;
    [[[UIApplication sharedApplication] delegate] setWindow:mainWindow];
  }
}

and the LaunchScreen in this case is a xib that looks the same as the LunchScreen.storyboard I set up in the settings of the project

Thanks :) it works now. But I had to upgrade RNN to min v5.

Yes I created a new ui view controller.
Here is my full code

// The only way to show the splash screen over the JS ui and without blocking the thread
  rootViewController = [UIViewController new];

  _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  _window.backgroundColor = [UIColor clearColor];
  _window.userInteractionEnabled = NO;
  _window.rootViewController = rootViewController;
  rootViewController.view.userInteractionEnabled = NO;

  [RNSplashScreen showSplash:@"LaunchScreen" inRootView: rootViewController.view];

  [_window setHidden:NO];

  t = [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: @selector(onHideSplashScreen) userInfo: nil repeats:YES];

  return YES;
- (void)onHideSplashScreen  {
  // I want to die for implementing this like that, but I don't have a choice right now :(
  if (rootViewController.view.subviews.count == 0) {
    [t invalidate];
    t = nil;
    [[[UIApplication sharedApplication] delegate] setWindow:mainWindow];
  }
}

and the LaunchScreen in this case is a xib that looks the same as the LunchScreen.storyboard I set up in the settings of the project

Thanks :) it works now. But I had to upgrade RNN to min v5.

happy I could help

I had no idea this was my issue until I stumbled upon this issue and tried out your solution, @Rotemy. I did not need the NSTimer as you used, but switching away from [RNSplashScreen showSplash] allowed me to control hiding the splash screen in JS as expected.

Seems like showSplash has a conflict with some underlying API used by react-navigation and potentially other popular libraries. Would love to dig into it further but that's all I can assume at this point.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Dineshchitta picture Dineshchitta  路  5Comments

ijry picture ijry  路  5Comments

zhaogao picture zhaogao  路  4Comments

johndo31 picture johndo31  路  3Comments

TsuryKnox picture TsuryKnox  路  5Comments