iOS 启动屏

新版 iOS 使用 .storyboard 文件作为启动屏文件,RN 自带了一个 启动屏,在生成项目的路径为 ios/[project]/LaunchScreen.storyboard,如果可以接受纯文字格式的启动屏,打开这个文件修改文字即可。

若需要自定义,可通过 xcode 进行可视化编辑,如下图

.storyboard 编辑

上图所标注的地方为主要操作区域

  1. 点击 + 号按钮,拖拽 UIImageVIew 到屏幕窗口。
  2. 选择要编辑的图层或约束条件
  3. 设置当前选中图层的属性
  4. 添加约束条件

可通过上述方法直接编辑 LaunchScreen.storyboard 或新建一个 .storyboard 文件,最后可通过以下方式设置启动屏所用文件,RN 默认已设置了 LaunchScreen.storyboard 为启动屏,若直接修改该文件,则无需进行这一步。

设置启动屏文件

下面展示两种常见的启动屏设计

一张居中的 LOGO 图
上下各一张图

另外,启动屏可能存在一定的 瑕疵,使用时要注意一下。

与 Android 的不同之处

相比 Android 启动屏,iOS 启动屏类似于 Android 使用 activey 作为启动屏的方案,而没有启动背景的方案。这意味着可以有更好的灵活度,可以制作更加复杂的效果(上面只是最简单的介绍,更多玩法需自行探索)。并且该启动屏会在主页面加载成功后移除屏幕,替换为主界面,主界面是何时载成功是由接口函数反馈的,在 AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    .....

    // 该函数处理完毕后返回结果,此时启动屏移除屏幕
    return YES;
}

对于 RN 而言,该过程发生在主线程,在处理该逻辑的同时,JS 线程会同步加载并执行,若在主线程处理完毕、启动屏幕移除的时候,JS 线程还未处理完毕(即主界面未完成渲染),此时会显示为白屏。

一般情况下,若 JS 线程在启动时没有任何异步任务,直接在 render 返回界面,倒也问题不大,几乎不会出现白屏的情况,但如果 JS 在启动时执行一些异步请求,之后才 render 界面,那么这个白屏就很难受了。

这不同于 Android 使用 window 背景图的方式,背景图不会消失,直到主界面渲染完成后自动覆盖,视觉上是连贯的。所以对于 RN 而言,直接使用 .storyboard 作为启动屏并不完美。

react-native-splash-screen 的方案是,使用 NSRunLoop 方法阻塞主线程,等待 JS 线程加载完毕的通知,待收到通知后,解除阻塞,移除启动屏,显示主界面。

react-native-bootsplash 的方案是,在未移除启动屏前,复制启动屏创建一个层,覆盖到主界面的上面,此时看到的是这个复制的层,但完全一样,之后启动屏会按预期移除,整个过程视觉上是没有任何变化的。待主界面加载完毕,JS 线程发送通知,此时移除覆盖在主界面上的层,显示主界面。

二者都需要在 AppDelegate.m 添加相应的代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    .....
   
    // react-native-splash-screen 需再此调用函数阻塞主线程,收到通知后跳出循环

    // react-native-bootsplash 在此调用函数,即启动屏移除前,创建一个完全一样的层

    // 该函数处理完毕后返回结果,此时启动屏移除屏幕
    return YES;
}

这两种方式,第二种要更好一点,阻塞主线程不是一个好主意。之所以能够在 RN 上使用,是因为 RN 的 JS 单独使用了一个线程,如果为原生开发,阻塞主线程就死循环了。即使对 RN 而言,也最好不要使用这种方式,因为可能有其他第三方组件需要在主线程执行一些任务。

对于第二种方式,可以将复制的启动屏插入到主界面的下面,这样就与使用 Android 启动背景的逻辑一致了,主界面渲染完毕后会自动覆盖启动屏,哪怕不移除这个复制的层也没什么影响。react-native-splashbg 便是使用这种方式。

继续:

Android 启动屏
React Native 启动屏

你可能感兴趣的:(iOS 启动屏)