“'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 没有持久存储。'”的主要内容,如果未能解决你的问题,请参考以下文章