iPhone设备上核心数据应用程序崩溃了。

4

你好,我在设备上测试我的核心数据应用程序,但在 iPhone 上崩溃,在模拟器中却可以工作正常。这是我的代码:

- (NSManagedObjectContext *)managedObjectContext {

    if (managedObjectContext != nil) {
        return managedObjectContext;

    }
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc] init];
        [managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return managedObjectContext;
}



- (NSManagedObjectModel *)managedObjectModel {

    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TouristGuide" withExtension:@"momd"];
    managedObjectModel= [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
    NSLog(@"%@", modelURL);
    return managedObjectModel;
}


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {


    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:@"TouristGuide.sqlite"];


    NSFileManager *fileManager = [NSFileManager defaultManager];
    // If the expected store doesn't exist, copy the default store.
    if (![fileManager fileExistsAtPath:storePath]) {
        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"TouristGuide" ofType:@"sqlite"];
        if (defaultStorePath) {
            [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
        }
    }

    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];


    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];    
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];


    NSError *error;
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }    


    return persistentStoreCoordinator;
}

设备日志显示异常,位于以下行:

persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

例外是无法使用空模型创建nspersistancecordinator和第二个是找不到实体“城市”。如何解决这个问题?崩溃日志。
0x352d1de0 -[NSPersistentStoreCoordinator initWithManagedObjectModel:] + 252 10  TouristGuide                   
0x0000358e -[TouristGuideAppDelegate persistentStoreCoordinator] (TouristGuideAppDelegate.m:176) 11  TouristGuide                  
0x0000310e -[TouristGuideAppDelegate managedObjectContext] (TouristGuideAppDelegate.m:124) 12  TouristGuide     
0x000041f6 -[CityViewController viewDidLoad] (CityViewController.m:43)

你的模型有几个版本,还是只有一个? - FKDev
什么是两个异常?从相关问题来看,那不是已经解决了吗?这对我来说似乎是一样的。 - Deepak Danduprolu
第一个是无法使用空模型创建nspersistancecordinator,第二个是找不到实体城市。 - iProgrammer
2个回答

18
按住 Option 键,转到“Product”菜单(Xcode 4),然后执行“Clean Build Folder”,然后松开 Option 键并执行“Clean”操作。
现在选择“Product”菜单 > “Analyze”,确保一切正常。
最后,转到项目查看器的左侧面板,并单击表示整个项目的图标。在主面板中弹出的窗口中,在“Targets”下单击您的应用程序。现在点击“Build Phases”,展开“Copy Bundle Resources”。确保您的 TouristGuide.xcdatamodeld 文件在那里。接下来,展开“Link Binary with Libraries”,确保“CoreData.framework”在其中(如果您将 Core Data 添加到原本不是 Core Data 项目的现有项目中,则它可能不在其中)。接下来,展开“Compile Sources”,当然,仔细检查所有模型类是否都在其中(即 NSManagedObject 的自定义子类)。
说到这些模型类...现在点击您的 TouristGuide.xcdatamodeld,并点击“Default”配置。确保“Class”列中标有“NSManagedObject”的任何类都没有自定义类,并且如果它们列出了自定义类,请确保您具有相应命名的 .h 和 .m 文件。
也许与您的模型文件本身有关。有一次我更改了模型文件的完整路径(应该是 /Users/You/Documents/Developer/MyApp/MyModel.xcdatamodeld/MyModel.xcdatamodel)。一旦我更改了它,我就找不到如何将其更改回来了,因为 MyModel.xcdatamodeld 是一个“package”文件,而不是文件夹。当然,在 Finder 中,您可以执行“显示包内容...”,但是 XCode 用于选择文件位置的对话框拒绝导航到软件包内容中!所以我无法重新选择驻留在 .xcdatamodeld 文件中的 .xcdatamodel 文件!我不得不从头开始完全重新创建整个模型文件,这非常麻烦。也许有一种方法可以做到这一点,但我无法弄清楚。
另外,最后两个技巧。
首先是最后的技巧,尝试在备份项目上进行此操作,以防万一,但当我卡在那里时,它对我很有用:将代码从以下内容更改为:
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TouristGuide" withExtension:@"momd"];

变成这个样子:

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TouristGuide" withExtension:@"mom"];

……将“momd”更改为“mom”。

然后从设备或模拟器中删除应用程序,“清理构建文件夹”,“清理”,并重新构建和运行项目。它可能会给你错误,也可能不会。之后,再将其改回“momd”并重做所有这些步骤。这样做可能会让XCode删除比其他情况下更多的东西,并重新安装应用程序时生成一个新的“momd”文件。

倒数第二个技巧:

在头文件中添加#import,这也从来没有伤害过,只是为了好运。:D

希望这可以帮到你。如果有人能在开始时告诉我这些东西,那会省掉很多时间。


1
mom 文件是未版本化的文件,而 momd 是一个已经版本化的文件。 - TechZen
正确;一个.momd包含一个或多个.mom文件,对吧?但是我的希望是将文件类型暂时更改为错误的类型可能会“混淆”Xcode,使其认为必须重新构建它,如果构建方式存在问题,则可能有所帮助。这是一种最后的手段,如果从设备中删除不起作用,因为我听说过有时候它不起作用(例如,如果设备已越狱或者可能没有构建发布版)。 - CommaToast
我扩展了“复制捆绑资源”,但其中没有TouristGuide.xcdatamodeld文件。我该如何添加它? - iProgrammer
绝对漂亮的答案!哇。突然在发布版本上出现了这个问题。原来我的xcdatamodeld没有在复制包资源中。然而,这个bug直到xCode 6.3才出现。我相信这一定是一个bug,因为我找不到自上次成功部署以来的任何更改。无论如何,我学到了教训,将始终在发布版本上进行测试!感谢您的优秀帖子。 - SmileBot
不用谢。我很高兴这个答案四年后仍然能帮助人们。但是我并不高兴苹果到现在还没有把这个问题解决得更加完美...真的很烦...就像所有的Yosemite内核崩溃和延迟一样...唉... - CommaToast

1

错误实际上是由于self.managedObjectModel属性具有空值而引起的。查看加载managedObjectModel的方法。这就是问题的根源。

有时,Xcode在模拟器或设备上的开发构建中不会删除文件的先前版本。解决方案是手动删除整个应用程序并让Xcode从头开始重建它。


我尝试清理目标并重新安装应用程序,但它仍然无法工作。 - iProgrammer
手动删除应用程序,而不是使用Xcode,方法是按住应用程序图标,然后将其从设备中删除,然后重新安装。 - TechZen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接