react-native: iOS AppDelegate changes no longer permit configuring a loading view fade delay to avoid native -> JS "white flash"
New Version
0.71.1
Old Version
0.70.6
Build Target(s)
iOS
Output of react-native info
System: OS: macOS 13.2 CPU: (10) arm64 Apple M1 Pro Memory: 85.22 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 19.4.0 - /private/var/folders/lx/8pd1v4bj6656dm288zdsl9p00000gn/T/xfs-1926afa9/node Yarn: 3.3.1 - /private/var/folders/lx/8pd1v4bj6656dm288zdsl9p00000gn/T/xfs-1926afa9/yarn npm: 9.2.0 - /opt/homebrew/bin/npm Watchman: 2023.01.16.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.11.3 - /Users/craig/.rvm/gems/ruby-2.7.6/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1 Android SDK: API Levels: 24, 25, 26, 27, 28, 29, 30, 31, 33 Build Tools: 28.0.3, 29.0.2, 29.0.3, 30.0.1, 30.0.2, 30.0.3, 31.0.0, 33.0.0 System Images: android-28 | Google Play Intel x86 Atom, android-29 | Google APIs Intel x86 Atom, android-29 | Google Play Intel x86 Atom, android-30 | Google APIs Intel x86 Atom, android-30 | Google APIs Intel x86 Atom_64, android-30 | Google Play Intel x86 Atom, android-30 | Google Play Intel x86 Atom_64 Android NDK: Not Found IDEs: Android Studio: 2021.3 AI-213.7172.25.2113.9123335 Xcode: 14.2/14C18 - /usr/bin/xcodebuild Languages: Java: 11.0.12 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 18.2.0 => 18.2.0 react-native: 0.71.1 => 0.71.1 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found
Issue and Reproduction Steps
First of all, thank you for all the hard work improving React Native! The changes made to both the Android and iOS setup configs are great (and welcomed) however we are running into a challenge on iOS. Previously we could write something like the following:
NSDictionary *initProps = [self prepareInitialProps];
RCTRootView *rootView = (RCTRootView *)RCTAppSetupDefaultRootView(bridge, @"ExampleApp", initProps);
if (@available(iOS 13.0, *)) {
rootView.backgroundColor = [UIColor systemBackgroundColor];
} else {
rootView.backgroundColor = [UIColor whiteColor];
}
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
UIView *loadingView = [[storyboard instantiateInitialViewController] view];
[rootView setLoadingView:loadingView];
rootView.loadingViewFadeDelay = 0.5;
rootView.loadingViewFadeDuration = 0.5;
to, in the user’s eyes, delay the fade out of the launch screen to avoid the white flash between the native launch screen and our JS “splash” screen. This has been working well for countless releases. With the root view logic being internalized to the RN setup, it is not clear how to keep this behavior (if at all possible). From what I gather, the new architecture doesn’t have a mechanism to accomplish this either. So the ask is 1) expose some config variables for (existing architecture) to keep this functionality in place for those that currently use it 2) implement a way for the new architecture to have this same behavior (eventually the switch will be made).
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 8
- Comments: 46 (23 by maintainers)
Commits related to this issue
- Make sure not to override user background color Summary: When we introduced the RCTAppDelegate library, we prepared some template methods for the user to customise their views. However, after they c... — committed to cipolleschi/react-native by cipolleschi a year ago
- Make sure not to override user background color (#36215) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36215 When we introduced the RCTAppDelegate library, we prepare... — committed to cipolleschi/react-native by cipolleschi a year ago
- Make sure not to override user background color (#36215) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36215 When we introduced the RCTAppDelegate library, we prepare... — committed to facebook/react-native by cipolleschi a year ago
- Make sure not to override user background color (#36215) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36215 When we introduced the RCTAppDelegate library, we prepare... — committed to OlimpiaZurek/react-native by cipolleschi a year ago
Hi @gtokman, you are right.
Currently, there is a bug in RN 0.71 for the
backgroundColor
only, as explained it here. Basically, you can customize the view, but then we will replace the background color. 🤦This will be fixed in 0.72, but I can try to backport it to 0.71.
Meanwhile, what you can do is the following:
And it will do the trick
Potential workaround:
Here is another example that worked for me:
And here is a link to convert HEX and RGB into UIColor: https://www.uicolor.io/
@zallanx @gabriellend @mysport12 @jafar-jabr @alpha0010: please, refer to my comment above as the proper way to customise your
View
s andViewController
s is to override template methods theRCTAppDelegate.h
class provides you.Let me know if they work (as they should). Meanwhile, I’ll close this issue.
I tested the repro and with the proper patch, it is fixed (no white flash anymore). This is the right fix for both architectures:
The
createRootViewWithBridge
method returns a differentUIView *
based on the architecture you are building against.There is still a bug in the New Architecture that makes the flash appear, currently, but it is in the internals. It has to work this way.
We are also working on the APIs to make sure we can soon remove those ugly
#ifdefs
.But on the old architecture, it works properly.
Actually, you can do whatever you want with the RootView.
The RCTAppDelegate.h exposes methods that you can override in order to customise your views.
For example, this method allows you to get the default UIView * and to customise it:
And there are a method to customise the view controller if needed.
I’m sorry to see this issue only now.
@mysport12 Running into the exact same issue while updating from React Native 0.70.0 to 0.71.0, thanks for posting. I used your example to do something a little different and thought I’d post too in case it’s helpful to anyone. For reference, I am also using Codepush and
react-native-bootsplash
.This is what my launch options looked like at React Native 0.70.0, with the main things to note enclosed by
**
:This is what it looked like after 0.71.0:
Big difference!
rootView
was completely gone so I couldn’t setbackgroundColor
that way anymore. Here is what worked for me after tailoring your solution:Native files are not my strong suit at all, basically just learning them off the cuff. If anyone comes across this and believes I’m missing something/implemented this incorrectly, I’m very open to correction.
@alpha0010 your solution didn’t get me all the way there but provided me with enough insight to get things working as intended (see below)
@jafar-jabr I couldn’t seem to get your solution to work as is but like alpha’s proposed solution, gave me clues into what I needed to do.
@cipolleschi Yep, that’s done it 🙂
Thanks for the quick response
Both tried 😄
Definitely, though might take some time, thank you
Property ‘loadingView’ not found on object of type ‘UIView *’
Oh… I understood what’s the culprit.
What we did, to simplify the client code, was to encapsulate the initialization logic into the
RCTAppDelegate
class. The reason is that , in that way, we can minimize changes for you in the future, with the hope not to touch the AppDelegate ever again (I guess you’d love a simplified update experience, right?).In doing so, we moved the code as it was to that class, adding some hooks you can override to further customization.
Among these hooks, there is
createRootViewWithBridge
that is used to create the view at line 55. The problem is that, 2 lines below, we preset the background color for you.So, given that you are actually updating the only property the AppDelegate is modifying, your change get lost. 😦
So sorry for this. I’ll create a task for myself to expose a last resort method to customize the
rootViewController
, hence giving you the final word on it and on itsrootViewController.view
objects.How does this sound?
I’m sorry for the disruption it may has caused.
The gist of the above being that it seems to work when the loading view is set AFTER the window is set. Combined approaches with code snippets below for conciseness
Pre 0.71.0 (working):
0.71.X
BOOL success = [super application:application didFinishLaunchingWithOptions:launchOptions];
(working):0.71.X createRootViewWithBridge (not working - launch screen image scaling oversized):
Appreciate the dialog and the assistance on this FWIW. It seems to have helped others as well which is always beneficial.
Thanks @gabriellend, the suggested code worked out great.