1

我收到此错误:操作无法完成。(Cocoa 错误 134140。) *由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“未找到指定的持久存储。”

我刚刚更改为我的数据模型的新版本。但是,如果我激活以前版本的数据模型,则该应用程序可以正常工作。如果我激活新版本,我会收到该错误。我所做的唯一更改是我将数据模型中的所有变量都设置为非可选变量,这些变量应该能够由自动迁移功能处理。我不明白为什么它说它找不到持久存储,当 [fileManager copyItemAtPath:defaultStorePath toPath:myPathDocs error:&error] 没有抛出错误时。

我似乎认为这与我的主包中的 sqlite 文件来自旧版本的数据模型,但没有来自新版本的 sqlite 文件这一事实有关。但是,我的印象是自动迁移只会为新模型自己生成一个新文件(?)并将现有文件中的数据迁移到其中。这是错的吗?

在我的 iOS 应用程序中,我的资源中有一个名为 Formats.sqlite 的文件。在全新安装后启动时,应用程序会查看应用程序的 /Documents 文件夹中是否存在现有的 Formats.sqlite。如果没有,它会将主包中的那个复制到那里。在我制作新版本的模型之前,这一切都很好。这是我使用的代码:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    int count = [[persistentStoreCoordinator persistentStores] count];
    if (persistentStoreCoordinator != nil && count) {
        return persistentStoreCoordinator;
    }
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:@"Formats.sqlite"];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error = nil;
    if (![fileManager fileExistsAtPath:myPathDocs]) {
        NSLog(@"SQLite file not found, copying SQLITE file");
        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"Formats" ofType:@"sqlite"];
        if (defaultStorePath) {
            if(![fileManager copyItemAtPath:defaultStorePath toPath:myPathDocs error:&error]) {
                NSLog(@"Error copying file at defaultStorePath to the documents path: %@",error);
            }
        }
    }
    storeURL = [NSURL fileURLWithPath:myPathDocs];
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
                             nil];
    if (persistentStoreCoordinator == nil) {
        persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    }
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    {//my error code here}

So then the error gets thrown where it says "my error code here." What do I do in order to fix this? Why is this happening? Incidentally the console spits out all the steps for the migration, so it looks like it's trying to do it, but then it can't find the persistent store, which I don't understand why it can't find it, since it's been added in the build targets.

I just want to make sure that if people upgrade from previous versions of the app, their data gets migrated over and they don't have to re-enter everything. Thanks!

4

1 回答 1

0

To find the source of the error, I used this code to get the most detailed description of the error from the debugger:

    NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
    if(detailedErrors != nil && [detailedErrors count] > 0) {
        for(NSError* detailedError in detailedErrors) {
            NSLog(@"  DetailedError: %@", [detailedError userInfo]);
        }
    } else {
        NSLog(@"  %@", [error userInfo]);
    }

Then after using that code, the error message said that one of the properties in my model did not have a default value, and that it would need one for the automatic migration to work correctly. After I added the default value for that property, then everything worked.

The above code snippet is very useful for debugging Core Data errors because without it, Core Data won't necessarily tell you which exact property in your model is the source of the problem. Using the "detailedError" code gave me the exact info I needed. Thanks, "detailedError."

于 2012-06-10T18:24:07.643 回答