迁移Core Data存储时出现错误消息
问题:
我有一些非常简单的代码(如下),在“ migratePersistentStore
”期间会导致出现exception并显示错误消息
Exception:*** -[__NSArrayM replaceObjectAtIndex:withObject:]: object cannot be nil
代码:
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); } }
更多信息:
- 看来,如果没有数据存在,则不会发生exception。 而相同的函数设置一个错误,与userInfo“ 不能添加两次相同的存储 ”。
- 我正在做一个简单的小项目来尝试复制这个问题,一旦完成,我会在这里发布一个链接。
显然,当您的iCloud URL和本地URL相同时,Core Data不喜欢迁移。 我认为这应该不重要,因为真的,iCloud的数据存储在自己的目录。 但是,在迁移期间,似乎使用相同的名称会导致问题。
轻松修复 – 只需要做这样的事情:
- (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"]; } }
这里真的没有足够的信息来告诉你确切的原因。 正如你可能已经猜到的,CoreData正在运行一个问题,它将用一个零对象replace一个数组中的一个对象。 如果您的映射模型不匹配,就会发生这种情况。
要解决您的问题,您应该做两件事:
-
除去try / catch,而是为所有exception设置一个符号断点。 这会导致debugging器在遇到此exception时停止,并且您可以看到堆栈跟踪以及应用程序中发生的其他事情。 请注意,如果CoreData运行到合并冲突,这些在CoreData内部作为exception处理,debugging器也将停止。 在这种情况下,直到数组exception。
-
设置你的应用程序的启动参数来打开迁移日志logging来看看它到底是如何实现的。 在Xcode中,编辑您的应用程序scheme的运行任务以传递
-com.apple.CoreData.MigrationDebug
。 请注意,论点之前的破折号很重要。 CoreData将logging你的迁移过程中发生的情况,这应该有助于查明问题。
随机猜测:你有没有在你的模型中声明NSManagedObject
子类,你忘记了在你的构build中包含一个实现? 在这种情况下,迁移代码尝试创build自定义子类的实例是不可能的,然后在将结果投入数组之前无法检查成功。
在没有迁移的情况下运行并执行类似以下操作来检查:
for(NSEntityDescription *entityDescription in model.entities) { NSString *className = [entityDescription managedObjectClassName]; Class class = NSClassFromString(className); if(className && !class) NSLog(@"An implementation of class %@ is missing from the build", className); }