在状态恢复期间显示应用程序屏幕快照而不是 launchScreen

App screen snapshot being shown instead of launchScreen during state restoration

我遇到了这种情况,我第一次为支持 iOS 9.3 及更高版本的新应用程序添加了应用程序状态恢复 API。状态恢复在功能上运行良好,但我注意到由于状态恢复期间的延迟,它显示的是屏幕快照而不是 LaunchScreen.xib 内容。通过快照,我指的是自动屏幕截图 iOS 在您的应用程序 UI 进入后台时拍摄。

如果你不知道什么是应用程序状态恢复,它是 iOS 6,这是来自 Apple 的 link:

Apple Documentation on App State Saving & Restoring

在这个应用案例中显示屏幕快照是一个严重的问题,因为这个特定的应用有大约 4 秒的延迟,iPhone 4s 运行 iOS 9.3.5,在应用程序状态恢复期间执行。用户会认为该应用程序已挂起,因为在此期间未显示启动/启动屏幕。这种情况在模拟器和设备上当前可用的所有 iOS 版本上重现。

如何防止显示快照,并强制始终使用 LaunchScreen.xib,同时仍然保留应用程序状态 save/restore 功能优势?

经过研究,我发现Apple很早就提供了UIApplication之外的方法来处理这种情况。但它的用法,即使在今天,也很少被记录下来。

解决方案是使用 UIApplication 中的 ignoreSnapshotOnNextAppliationLaunch 方法。

Apple ignoreSnapshotOnNextApplicationLaunch method

您必须按照 Apple 的建议通过 UIApplication 单例模式访问它,我将在此处解释:

Apple UIApplication sharedApplication method

在哪里使用这个是没有明确记录的,我在这里分享。 ignoreSnapshotOnNextApplicationLaunch 方法将完全无效,除非在 iOS 从视图控制器保存应用程序状态时特别调用。例如当您点击主页按钮使应用程序成为背景时。

您不能直接从处理背景/前景转换的 AppDelegate 方法中调用此方法,因为它需要在保存状态以供以后恢复时从视图控制器中调用。

Apple 为这个保存任务提供了 UIViewController 的 encodeRestorableStateWithCoder 方法

Apple encodeRestorableStateWithCoder method

这就是我们需要做出改变的地方。如果进行状态恢复,您应该已经拥有它;但是通过将此方法调用添加到每个视图控制器 class 中,您在故事板中设置了恢复 ID,或者手动保存状态,您可以通过从 UIApplication 单例中包含 ignoreSnapshotOnNextApplicationLaunch 来避免使用任何快照。这将不会阻止iOS拍摄快照,只是在重新启动时恢复应用程序状态时不会显示它。

// save any app state information that is not already saved automatically
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {

    // prevent taking a screen shapshot and force launchScreen xib to be used always
    [[UIApplication sharedApplication] ignoreSnapshotOnNextApplicationLaunch];

    [super encodeRestorableStateWithCoder:coder];

    return;
}

请务必在测试期间添加此应用程序后重新设置应用程序后台,以便 iOS 删除之前保存的快照文件。