wix / react-native-navigation

A complete native navigation solution for React Native
https://wix.github.io/react-native-navigation/
MIT License
13.04k stars 2.67k forks source link

[V2] [iOS] Quick white screen (flash) after LaunchImage #3661

Closed Dexwell closed 5 years ago

Dexwell commented 6 years ago

Issue Description

Between the LaunchImage and display of the first RNN screen, there is a small window where the screen is white. In Debug mode it takes longer; this is where you see the green "Downloading JavaScript bundle" bar up top. The statusbar also goes dark here even though I set it to light using UIStatusBarStyle in Info.plist.

Existing solutions exist that require editing AppDelegate.m code related to the rootView. However when using RNN this is impossible, since we have to replace everything with a custom bootstrap method:

[ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions];

Is there any way you guys on the native side could make it so that the launch image and UIStatusBarStyle are not changed until the first RNN screen has loaded? This is some critical functionality impacting the UX of every app using RNN.

Steps to Reproduce / Code Snippets / Screenshots

n/a


Environment

danielgindi commented 5 years ago

Okay so a lot of work was done on master branch already, and we have one leftover which is the bugs with the splash screen itself. A PR is here: https://github.com/wix/react-native-navigation/pull/4698

You could do the same as before - work with the latest version and compile the iOS part from danielgindi:bugfix/ios_splash_status_bar branch.

pod 'ReactNativeNavigation', git: 'https://github.com/danielgindi/react-native-navigation.git', branch: 'bugfix/ios_splash_status_bar'
guyca commented 5 years ago

We'll merge #4698 today and publish a new version. Thanks for all the work you're doing @danielgindi, this feature is happening thanks to your efforts 🙇

danielgindi commented 5 years ago

@guyca I'm just grateful for the work you guys have done and for Wix open sourcing some of their projects. I believe in open source.

danielgindi commented 5 years ago

Now with 2.10.0 I think this issue can finally be closed! @Dexwell

Dexwell commented 5 years ago

@danielgindi Unfortunately, I don't think so 😓 I moved from your branch to the latest official release, and upon launch, the screen either still flashes white, or all components resize and bounce in as if a LayoutAnimation is happening. Quickly going back to your branch...

guyca commented 5 years ago

@Dexwell Have you setup waitForRender as shown in https://github.com/wix/react-native-navigation/issues/4369#issuecomment-461071990?

Dexwell commented 5 years ago

@guyca Yep. Perhaps it helps to know that I don't use RNN title components and hide them during initialisation:

Navigation.setDefaultOptions({
  topBar: {
    visible: false,
    animate: false
  }
});
danielgindi commented 5 years ago

For me it actually works on master. Setting waitForRender on the root component. Note that setting it in the defaults did not work for me, but on the actual setRoot call.

Dexwell commented 5 years ago

I set the waitForRender in both setRoot calls.

danielgindi commented 5 years ago

@Dexwell Is this in a release build or in debug? Because there's one difference from my original implementation, which is on the bridge's "reload" event, we didn't try to attach a not-so-ready view controller, so the splash screen persisted until the bridge finished reloading. In the new implementation, this does not happen - so bridge reloads cause a white screen, but in release builds there's no bridge reload event.

danielgindi commented 5 years ago

@Dexwell Basically the same configuration that worked with my branch should work on master, this is what works for me in release builds now.

Dexwell commented 5 years ago

@danielgindi Release, exact same code as with your branch triggers a flash/bounce.

Dexwell commented 5 years ago

Can you guys not reproduce the issue with LayoutAnimations?

Dexwell commented 5 years ago

I have another issue, which is showModal does nothing when called quickly in/after componentDidMount when using the Release scheme. Only works when calling showModal after 300 ms or so using setTimeout 😬

Did some testing, and the issue is there in both @danielgindi's 2.4.0 branch and the official 2.10.0, using the Release scheme. Not an issue when using the Debug scheme. In the official 2.4.0 there's no issue using either scheme.

Hope this is an easy fix 'cause I want to launch soon 😄

danielgindi commented 5 years ago

@Dexwell Please try with pod 'ReactNativeNavigation', git: 'https://github.com/danielgindi/react-native-navigation.git', branch: 'bugfix/ios_white_launch_screen_2', over 2.11.0. It's a new branch I made, that takes the work that was already merge to master, and adds that old trick of waiting for first UI event to be considered as rendered.

I haven't even tried to compile it with React Native yet, so you may have to fix some syntax errors or something like that. But the good news is that if it works for you, it's a very small gap to be merged to master.

About the showModal, please look for any warnings from iOS in the console. Something about presenting a view when ready or similar.

Dexwell commented 5 years ago

@danielgindi Thanks for your effort. It didn't help. To be clear, I'm using this code, then in that Root component the same to set to another screen.

Navigation.setRoot({
    root: {
      stack: {
        children: [
          {
            component: {
              name: 'Root',
              options: {
                topBar: {
                  title: {
                    component: {
                      waitForRender: true
                    }
                  }
                },
                animations: {
                  setRoot: {
                    waitForRender: true
                  }
                }
              }
            }
          }
        ]
      }
    }
  });

Regarding showModal, I can't view console logs because it only happens in the Release scheme. Even then, how would I know when RNN is ready to show a modal? It worked in the old versions. Perhaps useful: in this latest branch I did see the modal for like a split-second and then the original component again. The modal seems to be opened, but hidden/overlapped/interrupted.

danielgindi commented 5 years ago

@guyca Is it possible that it's "done waiting" when another request comes in? https://github.com/wix/react-native-navigation/blob/master/lib/ios/RNNCommandsHandler.m#L80

danielgindi commented 5 years ago

@Dexwell If my suspicions are correct, it might be showing the modal over the first view controller, and then removed when showing the second view controller.

I could try to write a fix that will take care of the synchronization for the first issue, which may also take care of the second one. But it's just a guess. I'll try to look at it later.

guyca commented 5 years ago

cc @yogevbd

Dexwell commented 5 years ago

Not to put you under any pressure @danielgindi 😄But do you have a rough idea of when you could take a look at this?

danielgindi commented 5 years ago

@Dexwell Sorry I got a lot of pressure in the last few days, I'll try to give it a go today

Dexwell commented 5 years ago

@danielgindi Take your time, I'm grateful for your help. Just seeing what the ETA is, otherwise I'll have to hack together a different solution to launch :)

guyca commented 5 years ago

@Dexwell If you could PR a screen to the playground app where this issue reproduces - we'll be able to take a look as well.

danielgindi commented 5 years ago

@Dexwell I looked at the code again, and didn't find a codepath where the situation I described could happen, unless React Native is doing something really bad under the hood. I mean it looks like the DidAppear notification (added as a subview) is filtered out if it's for a different view. There could still be a bug there.

Anyway, could you compile with the branch I mentioned and see that it actually compiles? Because I haven't tested it and it could just be failing. Also it should be relatively easy to debug in Xcode connected to your device, you'll see the ReactNativeNavigation code under the Pods project. Look for RNNReactView.m, specifically the function - (void)contentDidAppear:(NSNotification *)notification {. That's what I modified in the branch for you, and you could also test on master and on my branch.

Dexwell commented 5 years ago

@danielgindi It did compile after I changed

if (![appearedView.appProperties[@"componentId"] isEqual:_self.appProperties[@"componentId"]])

to

if (![appearedView.appProperties[@"componentId"] isEqual:self.appProperties[@"componentId"]])

and that's what I tested it with.

Dexwell commented 5 years ago

@guyca I can't seem to reproduce the issue in a simple lightweight sample project 😬

Dexwell commented 5 years ago

I at least made a test case where the root component appears over the modal. Basically when calling showModal in componentDidMount: https://github.com/Dexwell/react-native-navigation/tree/rnn-modal-bug

The Xcode console does say:

Presenting view controllers on detached view controllers is discouraged <RNNRootViewController: 0x7fe24bd3a100>

But it worked fine in 2.4.0. If we could just figure out what has changed from 2.4.0 to 2.10.0 that (only in Release!) makes the root component appear over the modal.

If you uncomment the setTimeOut in initial.js it works fine, but I want as few of those in my code as possible. (Also it still animates in even though the animation options tell it not to?)

Dexwell commented 5 years ago

@guyca @danielgindi I'll be submitting my app for review in a matter of days. Did you manage to take a look at the example project? I'd prefer to not ship on 2.4.0 with a flash, but that's less bad than modals not opening 😰

guyca commented 5 years ago

Hey @Dexwell, we've been a bit busy last two weeks. If the issue reproduces in that library we'll look into it soon, Thursday or Sunday next week.

danielgindi commented 5 years ago

@Dexwell did not get a chance, but if you want I can re-push the branch that worked for you, if you tell me what was the latest version that worked for uou with my branch (2.4.0?)

Dexwell commented 5 years ago

Some hopefully helpful info to narrow down the issue. On the latest 2.13.1:

What exactly does waitForRender: true do? Am I supposed to only call it once?

@danielgindi Thank you, but no need. I believe your 2.4.0 also had the modal bug, and 2.13.1 works, albeit with a flash.

Dexwell commented 5 years ago

In some cases I still had modal issues on 2.13.1, so I reverted to 2.4.0 and am using https://github.com/crazycodeboy/react-native-splash-screen to fix the flash. Still hope we find the cause of these issues so I won't be stuck at 2.4.0.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe the issue is still relevant, please test on the latest Detox and report back. Thank you for your contributions.

Dexwell commented 5 years ago

Still not completely fixed, bot.

acollazomayer commented 5 years ago

I fixed it with react-native-splash-screen.

How is your AppDelegate with react-native-splash-screen and react-native-navigation

Dexwell commented 5 years ago

@acollazomayer Call show after RNN code

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

  #ifdef DEBUG
    NSURL *jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
  #else
    NSURL *jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
  #endif

  [ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions];

  [RNSplashScreen show];

  return YES;

}
LRNZ09 commented 5 years ago

@danielgindi @Dexwell I have set waitForRender like this in default options:

animations: {
    setRoot: {
        waitForRender: true,
    },
},

And it does work, thanks!

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe the issue is still relevant, please test on the latest Detox and report back. Thank you for your contributions.

stale[bot] commented 5 years ago

The issue has been closed for inactivity.

haideralishah commented 5 years ago

Open The Script Build Phases in Xcode > Bundle React native Code and images see this export NODE_BINARY=/usr/local/bin/node ../node_modules/react-native/scripts/react-native-xcode.sh 1) open your teminal type which node to get node version path 2) replace node with your node version path after update NODE_BINARY path look like this export NODE_BINARY=/usr/local/bin/YOUR NODE VERSION PATH GOED HERE ../node_modules/react-native/scripts/react-native-xcode.sh reference : https://stackoverflow.com/questions/48639491/app-ios-stuck-on-blank-white-screen-when-build-release-react-native

dariakoko commented 4 years ago

@haideralishah Hi! Do you know what to do if after running 'which node' I get only '/usr/local/bin/'?

dariakoko commented 4 years ago

I found! "npm config list" command gives the correct path

And it didn't solve the issue in my case :(

Vivek-maven commented 4 years ago

Change js loading screen color from AppDelegate.m file by modifying the below line rgb color rootView.backgroundColor = [[UIColor alloc] initWithRed:0.0f green:0.0f blue:0.0f alpha:1];

JimTeva commented 1 year ago

For anyone still having this. The best thing to do right now is to add library react-native-splash-screen and only add this code in your first screen:

import SplashScreen from 'react-native-splash-screen';

...
componentDidMount() {
  ...
  SplashScreen.hide();
}