react-native-splash-screen icon indicating copy to clipboard operation
react-native-splash-screen copied to clipboard

Splash screen appears below JS content when using react native navigation

Open Rotemy opened this issue 4 years ago • 9 comments

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();.

Rotemy avatar Feb 12 '20 07:02 Rotemy

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?

niktonic21 avatar Mar 10 '20 14:03 niktonic21

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

Rotemy avatar Mar 11 '20 07:03 Rotemy

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.

niktonic21 avatar Mar 11 '20 08:03 niktonic21

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

Rotemy avatar Mar 11 '20 10:03 Rotemy

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.

cvharris avatar May 11 '20 16:05 cvharris

Can you guys share your AppDelegate.m file? I can't seem to get it to work.

aa-ar avatar Jul 12 '21 21:07 aa-ar

Can you guys share your AppDelegate.m file? I can't seem to get it to work.

Yes, same here. I would like to see the whole page of code to get mine to work also.

esegebart avatar Jun 22 '22 15:06 esegebart

  • (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]; } }

Where are you putting this at?

esegebart avatar Jun 22 '22 15:06 esegebart

I have this problem here, but happens only on Android, anyone can help me?

pedrobadm avatar Aug 17 '22 15:08 pedrobadm