刚入行react native不久,公司的一个项目启动不久,安卓先行了几个月,安卓也出现了从启动页到加载RN首页中间出现黑屏的现象。安卓是通过在启动页后加个自己写的欢迎页,同时监听js bundle 加载完成后,移除欢迎页解决这个问题。我参照这个思路,在网上搜了很多资料,解决了这个问题。记录一下。
先说现象:1.在我iphone11 系统17.3的真机上是启动页后出现1s左右的黑屏,第一次安装的话时间可能更久一点 2.在xcode15上的模拟器(系统17.2) 上是启动页后出现不到0.5s的白屏。
解决方案:
1.如果没有,请创建一个 LaunchScreen.storyboard 作为启动页
2.将 ViewController 的 Storyboard id 更新为 LaunchViewController。如下图:
3.在didFinishLaunchingWithOptions方法里再生成一个启动页(为了与启动页做区分在此称之为欢迎页吧,)并且加到当前的window上,同时添加RCTJavaScriptDidLoadNotification通知。收到通知后再延迟0.5s移除(因为发现还会有不到0.5s的黑屏/白屏闪现,时间很短)。AppDelegate.m代码如下:
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <CodePush/CodePush.h>
@interface AppDelegate ()
@property (nonatomic,strong) UIView *welcomeView;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"rgmboss";
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};
[super application:application didFinishLaunchingWithOptions:launchOptions];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:[NSBundle mainBundle]];
UIViewController*launchScrenViewController = [storyboardinstantiateViewControllerWithIdentifier:@"LaunchViewController"];
launchScrenViewController.view.frame=self.window.bounds;
self.welcomeView= launchScrenViewController.view;
[self.window addSubview:self.welcomeView];
//RCTJavaScriptDidLoadNotification 用于表示 JavaScript bundle 已经加载完毕
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reactNativeDidLoad) name:RCTJavaScriptDidLoadNotification object:nil];
return YES;
}
- (void)reactNativeDidLoad {
// 执行一些操作,比如更新 UI 界面等
[self performSelector:@selector(removeWelcomeView) withObject:nil afterDelay:0.5];
}
//移除欢迎页View(跟启动页一模一样的View)
- (void)removeWelcomeView{
[self.welcomeView removeFromSuperview];
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return[CodePush bundleURL];
#endif
}
@end
另外,查资料 很多人用开源插件expo-splash-screen 。大家也可以试一下。
本文章参考资料:
1.https://www.coder.work/article/8245205
2.https://stackoverflow.com/questions/64282146/react-native-black-screen-before-splash-screen-loads-ios