Did you change your Core Data model in your new version app? If not, I'd assume that the "migration" you mentioned means "copy," which can be done using replacePersistentStore(at:destinationOptions:withPersistentStoreFrom:sourceOptions:type:).
Otherwise, you might consider doing the migration (lightweight or staged migration depending on your change) first, and then copy the migrated store to your App Group container.
Secondly, your flow doesn't seem to cover the widget side. Consider your users do the following:
- Downloading and installing your app.
- Configuring and adding your widget before running your main app.
Now your widget can run before your main app being launched, or they can run simultaneously. If your widget goes ahead to create an empty store and put some data there, the data will be lost when your main app copies the existing store. Also, if the widget and main app access the UserDefault
simultaneously, a race will be triggered.
Without having the bigger picture, I may consider the following flow:
On the main app side:
- Check if the destination store URL exists. If yes, the copy is done, and so you continue the normal process.
- Otherwise, copy the store using
replacePersistentStore...
. - Set
hasMigratedToAppGroup
to true
in the shared UseDefault
. - Continue your normal process.
On the widget side:
- Check if
hasMigratedToAppGroup
in the shared UserDefault
is true
. If yes, continue your normal process. - Otherwise, present something in the UI to ask the user to launch the main app. With this, the widget doesn't access the store before it exists.
In this flow, hasMigratedToAppGroup
helps the widget avoid accessing the store while the main app is copying. If your widget doesn't really write data to the store, you can load the store in readonly
mode (See isReadOnly), and don't need the user default.