I encountered this situation where I had added app state restoration APIs for the first time to a new app supporting iOS 9.3 and higher. The state restoration is working fine functionally, but I noticed that it was showing a screen snapshot instead of the LaunchScreen.xib content because of the delay during state restoration. By snapshot I'm referring to the automatic screenshot iOS takes of your apps UI as it goes into the background.
If you don't know what app state restoration is, it came out with iOS 6, here's the link from Apple on it:
Apple Documentation on App State Saving & Restoring
Showing the screen snapshot in this apps case is a significant problem as this particular app has about 4 seconds of delay, on an iPhone 4s running iOS 9.3.5, to do during app state restoration. Users would perceive the app to be hung since the launch / splash screen was not being shown during this time. This situation reproduces on all iOS versions currently available, on both simulator and device.
How can I prevent the snapshot from being shown, and force the LaunchScreen.xib to be used always, all while still preserving the app state save/restore functionality benefits?
After researching this I found that Apple has long ago provided a method off of UIApplication to deal with this situation. But its usage, even today, is poorly documented.
The solution is to use the ignoreSnapshotOnNextAppliationLaunch method from UIApplication.
Apple ignoreSnapshotOnNextApplicationLaunch method
You will have to access it via the UIApplication singleton pattern as suggested by Apple here as I will explain:
Apple UIApplication sharedApplication method
The where to use this is what is not clearly documented and that I am sharing here. The ignoreSnapshotOnNextApplicationLaunch method will have absolutely no effect unless specifically called when iOS is saving the app state from the view controller(s). Such as when you tap the home button to background the app.
You cannot call this method directly from the AppDelegate methods dealing with background / foreground transitions, as it needs to be called from the view controllers while their states are being saved for later restoration.
For this saving task Apple provides the encodeRestorableStateWithCoder method from UIViewController
Apple encodeRestorableStateWithCoder method
And this is where we need to make the change. If doing state restoration you should already have it; but by adding this method call to each view controller class where you have setup restoration IDs in storyboard, or are saving state manually, you can avoid any snapshots being used by including the ignoreSnapshotOnNextApplicationLaunch from the UIApplication singleton. This will not prevent iOS from taking the snapshot, just not showing it during app state restoration on re-launch.
// 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;
}
Be sure you re-background the app after adding this during your testing, to have iOS delete the previously saved snapshot file.