我的应用程序最近一直在崩溃,只在iOS9上发生崩溃#
致命异常:NSInternalInconsistencyException
此NSPersistentStoreCoordinator没有持久存储(损坏的文件)。它无法执行保存操作。
报告的最后一次电话是
-[NSPersistentStoreCoordinator _coordinator_you_never_successfully_opened_the_database_device_locked:]
这就是NSPersistentStoreCoordinator的创建方式
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSURL *storeURL = [[delegate applicationDocumentsDirectory] URLByAppendingPathComponent:@"database.sqlite"];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
NSError* error = nil;
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES} error:&error])
{
NSLog(@"Error adding persistent store. %@, %@", error, error.userInfo);
return nil;
}
return _persistentStoreCoordinator;
}
有人知道造成这些崩溃的原因是什么吗?
答案 0 :(得分:4)
我在iOS9上没有遇到过这个错误。但是,您应该查看日志以查看您遇到的错误。您是否有可能遇到了#34;错误添加持久存储"创建PSC后?
您的方法存在一个问题,即如果您遇到该错误,后续调用将返回既不是零也不正确设置的PSC。
原因是您在成功设置之前指定了_persistentStoreCoordinator
。因此,如果有任何错误,则返回nil,但下次调用该方法时,将返回没有存储的PSC。
无论如何,您应该更改该方法,以便您只返回零或完全可操作的PSC。
我会将这种方法改为这样的方法。但是,注意,我永远不会像这样构建核心数据堆栈。但是,至少以下代码将修复您的错误,您可以返回部分构成的PSC。
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSURL *storeURL = [[delegate applicationDocumentsDirectory]
URLByAppendingPathComponent:@"database.sqlite"];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:self.managedObjectModel];
NSError *error = nil;
if (![psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:@{NSMigratePersistentStoresAutomaticallyOption:@YES,
NSInferMappingModelAutomaticallyOption:@YES}
error:&error]) {
NSLog(@"Error adding persistent store. %@, %@", error, error.userInfo);
} else {
_persistentStoreCoordinator = psc;
}
return _persistentStoreCoordinator;
}
修改强>
评论中没有足够的空间来回答你的问题,所以我把它放在这里。
@JodyHagins - 另外,你提到你不会构建你的 像这样堆叠,你能让我知道我的堆栈有什么问题吗? - AWillian
我发表了评论,因为您发布的代码与默认的Xcode核心数据模板非常相似。你调用app-delegate获取目录,表明这不在app-delegate中,这很好。
然而,该方法表明您从"任何地方访问它是懒惰的#34;这告诉我你的堆栈不是像我构建堆栈那样构建的(特别是因为你还包含了迁移选项)。
我并不意味着暗示你所做的事情本身就是错误的,只是因为我不怎么做。
现在,我会第一个说我所做的就是我所做的......而且我不能说它是正确的方式......只是我的方式。事实上,我没有看到其他任何人真正做我做的事情(我实际上是NSManagedObjectContext的子类,虽然我介意警告并远离那些笨拙的位)。这本身可能表明我所做的可能不适合您或其他任何人。但是,我发现它适合我,以及我必须实施的相当复杂的应用程序。
那么,我将如何建立一个堆栈?
嗯,这比SO答案更值得深入,所以我要简短。它还取决于哪种类型的堆栈 - 父/子,具有相同PSC的兄弟姐妹,具有不同PSC但同一商店的堂兄弟。
首先,我不提供对模型和协调员的单独访问。您可以轻松地从上下文中访问这些内容,并且通常最终导致的问题多于其价值。
除了测试和琐碎的例子之外,我总是异步创建我的MOC,就像这样......
+ (void)createWithConcurrencyType:(NSManagedObjectContextConcurrencyType)concurrencyType
completion:(void(^)(NSManagedObjectContext *moc, NSError *error))completion;
创建MOM并将其分配给PSC,创建PSC并将其分配给MOC。它以异步方式发生,因此可以在后台线程中完成可能很长的打开和初始化过程。完成处理程序在performBlock
内调用,因此可以干净地使用MOC。这也可以防止在完全设置和读取MOC之前使用。
即使使用主队列并发类型调用,所有工作都在后台线程中完成,因此只在主线程上调用完成。
在为导入和临时目的创建相关MOC时,我也使用相同的模式。
答案 1 :(得分:2)
来自Apple开发论坛here的回答,其中也解释了可能的原因和解决方案。
原因在于描述符:您的应用程序在设备被锁定时尝试打开持久存储,并且您的代码在数据保护API上跳闸。
这就是你在新设备和新iOS版本上绊倒的事情,因为新设备足够快,可以在转换完成数据保护代码之前让你的应用运行。
此类问题的解决方案可能如下所示
您几乎必须进入启动代码,然后重写它以便检查受保护数据是否可用,然后延迟启动Core Data,直到applicationProtectedDataDidBecomeAvailable。