“'NSInternalInconsistencyException' 的替代原因,原因:'此 NSPersistentStoreCoordinator 没有持久存储。'”

Posted

技术标签:

【中文标题】“\'NSInternalInconsistencyException\' 的替代原因,原因:\'此 NSPersistentStoreCoordinator 没有持久存储。\'”【英文标题】:Alternate Causes for "'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores.'"“'NSInternalInconsistencyException' 的替代原因,原因:'此 NSPersistentStoreCoordinator 没有持久存储。'” 【发布时间】:2014-01-21 17:29:22 【问题描述】:

感谢阅读。我们收到了关于我们的 ios 应用程序的崩溃报告,其中包含以下错误:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores.  It cannot perform a save operation.'

这发生在我们的主队列 NSManagedObjectContext 尝试保存时:

BOOL saved = [managedObjectContext save:&error];

这发生在通过以下方式提交的块中:

[managedObjectContext performBlockAndWait:saveBlock];

互联网(尤其是 SO)对这个错误充满了解释,表明我们从来没有持久存储协调器(我们在构建核心数据堆栈时未能正确创建它)。但是,如果没有持久存储协调器,我们很难在程序执行中达到这一点。为了好玩,我注释掉了我们设置持久存储的行,应用程序几乎立即崩溃(没有进入我们的保存方法)。

有谁知道这个异常是否有其他原因,或者是否总是因为没有持久存储?有什么方法可以丢失持久性存储?

更多颜色:我们使用父/子 NSManagedObjectContexts 以便在后台线程中加载数据。完整的保存方法如下所示:

-(void)saveWithManagedObjectContext:(NSManagedObjectContext*)managedObjectContext successHandler:(void (^)())successHandler failureHandler:(void (^)(NSManagedObjectContext* managedObjectContext, NSError*))failureHandler

    void(^saveBlock)() = ^() 
        NSError *error = nil;
        BOOL saved = [managedObjectContext save:&error];
        if (!saved) 
            if (error != nil) 
                NSLog(@"Unresolved error saving %@, %@", error, [error userInfo]);
            
            failureHandler(managedObjectContext, error);
         else 
            if (managedObjectContext.parentContext != nil) 
                [self saveWithManagedObjectContext: managedObjectContext.parentContext successHandler:successHandler failureHandler:failureHandler];
             else 
                successHandler();
            
        
    ;

    BOOL isMainContext = managedObjectContext.parentContext == nil;

    if (isMainContext) 
        [managedObjectContext performBlockAndWait:saveBlock];
     else 
        [managedObjectContext performBlock:saveBlock];
    

它可以从后台线程调用,该线程将通过 performBlock: 在 NSManagedObjectContext 上调用 save:,然后在父 NSManagedObjectContext 上递归调用此方法以保存它。当应用程序崩溃时,它总是在主线程上,这是有道理的,因为主队列上下文是唯一需要持久存储的上下文。

非常感谢您的帮助。我确实在 devforums.apple.com 上发过帖子,所以如果您看到了两次,我深表歉意。

【问题讨论】:

【参考方案1】:

基本上有两个地方可以看。

首先,检查当您第一次将持久存储添加到 Core Data 堆栈时会发生什么。如果您使用的是 Apple 模板,那将在应用程序委托中,但通常在应用程序初始化时代码中的某处会调用

addPersistentStoreWithType:configuration:URL:options:error:.

其次,当您提到后台线程并且因为您将托管对象上下文传递给您的方法时,您可能有子上下文。在创建子上下文时,检查您是否已将有效的父上下文或存储协调器正确分配给子上下文。

【讨论】:

谢谢蒙迪。核心数据堆栈构建得很好(如果我在构建堆栈时将持久存储显式设置为 nil,应用程序几乎立即崩溃)。对于我的背景上下文,那些总是在实例化时立即设置其 parentContext。【参考方案2】:

不幸的是,这个错误是模棱两可的。我在使用配置时看到了它,并且配置名称中有错字,或者在模型中没有配置时传入了配置名称的一种情况。

所以我的第一行测试是查看您的 Core Data 堆栈创建代码。您能否将其添加到您的问题中,以便我们查看它?

【讨论】:

谢谢马库斯。我知道我的堆栈构建正确,因为如果我在构建堆栈时将持久存储显式设置为 nil,应用程序几乎会立即崩溃。 配置错误不等于设置为nil。配置错误稍后会出现,而不是立即出现。 我听说过(“设置错误的配置与将其设置为 nil 不同”),这只是让我快速了解如果我搞砸了堆栈设置会发生什么的方法.【参考方案3】:

我与Tom Harrington 离线通信,他发表了无伤大雅的评论:“除非您删除它们,否则永久存储不应该消失(我假设您不这样做)。” '当然,当我拆除核心数据堆栈(当用户注销时)时,我会这样做。当我拆除堆栈时,我会在我的根托管对象上下文(我唯一引用的)上调用重置,然后删除持久存储。但是,如果子上下文中有待处理的更改,它们将传播到我现在的持久无存储根上下文,导致保存时崩溃。由于父母上下文不跟踪他们的孩子是有充分理由的,所以我也不想跟踪他们。相反,我只是在调用 save 之前确认存在父上下文或持久存储协调器(至少有一个存储)。

【讨论】:

以上是关于“'NSInternalInconsistencyException' 的替代原因,原因:'此 NSPersistentStoreCoordinator 没有持久存储。'”的主要内容,如果未能解决你的问题,请参考以下文章

使用 CoreData 和 NSFetchedResultsController 删除 UITableView 行

从 uitableview 中删除 + 写入 plist 不起作用