I have noticed that if I kill the app from the multitasking view and open it immediately application(:didFinishLaunchingwithOptions:)
lifecycle method is not called but the sceneDelegate's scene(:willConnectTo:)
method is called.
As far as I know, the above implies the app is not deinitialised and still in memory even after killing and reopening the app.
And because of the above behaviour the NSPersistentContainer
object is still in memory and my Core Data stack setup code is present in scene(:willConnectTo:)
, so it's again initialised and it causes a crash with the following error :
Failed to load the Persistent Store due to: Optional(Error Domain=NSCocoaErrorDomain Code=134081 "(null)" UserInfo={NSUnderlyingException=Can't add the same store twice})
Here is my Core Data Stack setup:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
// Show splash screen
let viewController = UIStoryboard(name: "AppLoading", bundle: Bundle.main).instantiateViewController(withIdentifier: "AppLoadingViewController")
window.rootViewController = viewController
CoreDataManager.shared.setup {
// Always present the UI from a Main Thread
DispatchQueue.main.async {
if AppSettings.shared.onboardingFinished {
self.presentHomeUI(using: window)
} else {
self.presentOnboardingUI(using: window)
}
}
}
self.window = window
window.makeKeyAndVisible()
}
}
Is this normal behaviour of application(:didFinishLaunchingwithOptions:)
not called when app is killed an opened immediately ? another mystery is that this issue only affects iPhone X and above at least according to our crash logs.
If the above behaviour cannot be avoided then which method should be an ideal place for Core Data Setup ?
Here is a video of the crash that I am able to reproduce on a device: https://file.re/2021/05/07/sampleprojectappcrashvideo/
And here is a sample project that I created which demonstrate the crash: https://github.com/nik6018/CrashDemo (can only reproduce crash on iPhone X and above)
So I filled a DTS for the above issue with Apple as nothing on the internet helped me in understanding this issue.
So here's what Apple said:
scene(:willConnectTo:)
method the app crash as I am trying to initialise the store again even though an existing store is already present in memory.To resolve this issue I have 2 choices:
Move my Core Data Setup in App Delegate
Deinit my Core Data Manager when the app calls
sceneDidDisconnect(_:)
I went with option 2. and everything works as expected.
Honestly if I had watched the WWDC19 videos I wouldn't had to waste my DTS ticket :(
Hope this helps anyone if they come across this behaviour.