Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error message when migrating Core Data store

The Problem:

I've got some pretty simple code (below) that causes an exception during 'migratePersistentStore' with the error message

Exception:*** -[__NSArrayM replaceObjectAtIndex:withObject:]: object cannot be nil


The Code:

NSPersistentStore * oldStore = [_persistentStoreCoordinator persistentStores][0];

if (oldStore) {

    @try {

        [_persistentStoreCoordinator migratePersistentStore:oldStore 
              toURL:[self storeURL] 
              options: @{ NSPersistentStoreRemoveUbiquitousMetadataOption : @YES } 
              withType:NSSQLiteStoreType error:&error];

    }
    @catch(NSException* ex) {

        NSLog(@"Exception:%@", ex.description);

    }

}


Further Info:

  • It appears that if no data is present, the exception does not occur. Instead the same function sets an error, with userInfo "Can't add the same store twice".
  • I'm currently making a small simple project to try and replicate the problem, I'll post a link here once it's done.
like image 853
Jordan Smith Avatar asked Apr 05 '14 04:04

Jordan Smith


2 Answers

Apparently, Core Data doesn't like migration when your iCloud URL and local URL are the same. I thought this shouldn't matter because really, iCloud data is stored in its own directory. BUT, it seems during migration, using the same name causes problems.

Easy fix - just do something like this:

- (NSURL *)storeURL {

    NSURL * documentsDirectory = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:NULL];

    if (iCloudEnabled]) {
        return [documentsDirectory URLByAppendingPathComponent:@"iCloudEventData.sqlite"];
    } else {
        return [documentsDirectory URLByAppendingPathComponent:@"EventData.sqlite"];
    }

}
like image 100
Jordan Smith Avatar answered Nov 09 '22 23:11

Jordan Smith


There really isn't enough information here to tell you the exact cause. As you may have guessed, CoreData is running into a problem where it is replacing an object in an array with a nil object. This can happen if your mapping models do not match correctly.

To troubleshoot your problem, you should do two things:

  1. Remove that try/catch an instead set a symbolic breakpoint for all exceptions. This will cause the debugger to stop when it hits this exception, and you can see the stack trace and everything else that is going on in your application. Note that if CoreData runs into merge conflicts these are handled inside CoreData as exceptions and the debugger will stop on those as well. In that case, just continue until your array exception.

  2. Set your application's launch arguments to turn on migration logging to see how it's getting to this point. In Xcode, edit your application scheme's Run task to pass -com.apple.CoreData.MigrationDebug. Note that the dash preceding the argument is important. CoreData will log what happens during your migration, which should help pinpoint the problem.

What your scheme should look like

like image 21
quellish Avatar answered Nov 10 '22 01:11

quellish