You can clone with
I am using MCPersistentStoreMigrator in a production app, and it works great most of the time, but I do see this crash occasionally:
Exception Type: SIGABRT
Exception Codes: #0 at 0x3a925350
Crashed Thread: 8
Application Specific Information:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model'
Last Exception Backtrace:
0 CoreFoundation 0x000c22a3 __exceptionPreprocess + 163
1 libobjc.A.dylib 0x0000897f objc_exception_throw + 31
2 CoreData 0x00009339 +[_PFLock initialize] + 1
3 SimpleList-iPad 0x0012c21d -MCPersistentStoreMigrator setupContexts
4 SimpleList-iPad 0x0012c719 -MCPersistentStoreMigrator beginMigration
5 SimpleList-iPad 0x0010d48b -CoreDataController seedStoreWithMCPersistenStore:withPersistentStore:error:
6 SimpleList-iPad 0x001102c7 __63-[CoreDataController addUbiquityOptionsToStore:isForcedChange:]_block_invoke_3 (CoreDataController.m:1748)
7 libdispatch.dylib 0x0000211f _dispatch_call_block_and_release + 11
8 libdispatch.dylib 0x00005ecf _dispatch_queue_drain$VARIANT$mp + 143
9 libdispatch.dylib 0x00005dc1 _dispatch_queue_invoke$VARIANT$mp + 41
10 libdispatch.dylib 0x0000691d _dispatch_root_queue_drain + 185
11 libdispatch.dylib 0x00006ac1 _dispatch_worker_thread2 + 85
12 libsystem_c.dylib 0x00006a11 _pthread_wqthread + 361
13 libsystem_c.dylib 0x000068a4 start_wqthread + 8
No, I don't know why that would be. I assume you have passed a model to the initializer, correct? Is it possible that the model you are passing is nil for some reason?
The migrator just uses that model internally, and makes a copy of it.
Something else to beware of is using the migrator from two different threads. Make sure, for example, that you aren't somehow releasing the object before it is used. Shouldn't be possible, but something to think about.
This code works fine 95% of the time. But I've seen this crash report (using HockeyApp) dozens of times already, so it's a concern. The code that calls this is:
MCPersistentStoreMigrator *migrator = [[MCPersistentStoreMigrator alloc] initWithManagedObjectModel:store.persistentStoreCoordinator.managedObjectModel sourceStoreURL:seedStore.URL destinationStoreURL:store.URL];
migrator.sourceStoreOptions = seedStore.options;
migrator.destinationStoreOptions = store.options;
// Begin migration
BOOL migrationSucceeded = YES;
It is being called from within a dispatch_async block, but not from two threads; only from one place, and that blocks the UI so it shouldn't be called twice.
It should always be set, and it's only released after the seedStoreWithMCPersistentStore is done. Just as a precaution, I'll use [self managedObjectModel] instead, which should really be pointing to the same model instance), but will just try it out and see.
Also, inside [MCPersistentStoreMigrator initWithManagedObjectModel], I'm going to remove the originalManagedObjectModel and replace it with:
managedObjectModel = [model copy];
Since I always init the MCPersistentStoreMigrator object and use it without keeping any long-term reference to it, I shouldn't need to keep a "originalManagedObjectModel" around.
Not sure if these changes will make it better, because I can't confirm the source of the bug or get any repeatable steps, unfortunately. Thanks for the help!