Core Data migratePersistentStore crash with perform/performAndWait

(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?

Core Data migratePersistentStore crash with perform/performAndWait
 
 
Q