迁移Core Data存储时出现错误消息

时间:2014-04-05 04:59:50

标签: ios iphone objective-c ipad core-data

问题:

我有一些非常简单的代码(如下所示),在migratePersistentStore' 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);

    }

}


守则:

{{1}}


更多信息:

  • 如果没有数据,似乎不会发生异常。相反,同样的功能设置了一个错误,用户信息" 不能再添加同一个商店"。
  • 我目前正在制作一个小型简单项目来尝试复制问题,我会在完成后发布一个链接。

3 个答案:

答案 0 :(得分:7)

显然,当您的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"];
    }

}

答案 1 :(得分:5)

这里确实没有足够的信息告诉你确切的原因。正如您可能已经猜到的那样,CoreData正遇到一个问题,即它使用nil对象替换数组中的对象。如果映射模型不正确匹配,就会发生这种情况。

要解决您的问题,您应该做两件事:

  1. 删除try / catch,而不是为所有异常设置符号断点。这将导致调试器在遇到此异常时停止,您可以看到堆栈跟踪以及应用程序中正在发生的所有其他操作。请注意,如果CoreData遇到合并冲突,这些会在CoreData内部作为异常处理,调试器也将停止在这些异常上。在这种情况下,只需继续,直到您的数组异常。

  2. 设置应用程序的启动参数以打开迁移日志记录,以了解它是如何实现此目的的。在Xcode中,编辑应用程序方案的运行任务以传递-com.apple.CoreData.MigrationDebug。请注意,参数前面的破折号很重要。 CoreData将记录迁移过程中发生的情况,这有助于查明问题。

  3. What your scheme should look like

答案 2 :(得分:2)

随机猜测:您是否在模型中声明了任何NSManagedObject子类,而您忘记在构建中包含实现?在这种情况下,可以想象迁移代码可能会尝试创建自定义子类的实例,但是没有这样做,然后在将结果抛出到数组之前无法检查它是否成功。

在没有迁移的情况下运行并执行以下操作以检查:

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);
}