(I also posted this on StackOverflow at https://stackoverflow.com/questions/60196113/core-data-migratepersistentstore-crash-with-perform-performandwait)
I'm attempting to use `NSPersistentStoreCoordinator.migratePersistentStore(_:to:options:withType:)` to move a persistent store from one location to another, using an approach like this: https://useyourloaf.com/blog/moving-core-data-files/. (My overall goal is to create a backup, so I'm also drawing on the Ole Begemann's work (https://oleb.net/blog/2018/03/core-data-sqlite-backup/), which is in turn inspired by a previous SO post (https://stackoverflow.com/questions/22670273/copy-backup-persistent-store/22672386#22672386), but the problem I encounter is the same in both cases.)
let sourceStore = ... // NSPersistentStore
let backupFileURL = ... // URL
try self.migratePersistentStore(sourceStore, to: backupFileURL, options: [:], withType: NSSQLiteStoreType)
When calling `migratePersistentStore`, Core Data loads objects into memory, triggering a call to `awakeFromFetch()` on each one. That uses some memory, no surprise, but not necessarily a big deal in this case.
However, if `awakeFromFetch()` happens to do something that uses `NSManagedObjectContext.perform` or `NSManagedObjectContext.performAndWait`, the app crashes while moving the persistent store with an error like this one:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can only use -performBlock: on an NSManagedObjectContext that was created with a queue.'
As far as I can tell, the crash occurs because during the move/migration, `awakeFromFetch()` is being called in an NSManagedObjectContext that uses the deprecated `confinementConcurrencyType` and calls to perform/performAndWait aren't permitted on with that concurrency type.
(Here's a super simple example `awakeFromFetch()` that I'm using as a demonstration:)
public override func awakeFromFetch() {
super.awakeFromFetch()
managedObjectContext?.perform {
print("Hello, world!")
}
}
I could theoretically work around this by checking the context's concurrency type and only wrap calls in perform/performAndWait if it's not a confinement context, but that seems both unwieldy and out of line with best practices.
Does anyone have a recommendation for how to handle this? Is there a way to prompt `migratePersistentStore` to use a different concurrency type?