我的应用最近因 crashlytics 而发生这些崩溃,这只发生在 iOS9 上
Fatal Exception: NSInternalInconsistencyException
This NSPersistentStoreCoordinator has no persistent stores (corrupt file). It cannot perform a save operation.
报告的最后一次调用是
-[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;
}
有人知道是什么导致了这些崩溃吗?
最佳答案
我在 iOS9 上没有遇到过这个错误。但是,您应该查看您的日志以了解您有什么错误。是否有可能您在创建 PSC 时遇到了“添加持久存储时出错”?
你的方法有一个问题,如果你遇到那个错误,后续调用将返回一个既不是 nil 也不是正确设置的 PSC。
原因是您在成功设置之前分配了 _persistentStoreCoordinator。因此,如果有任何错误,您将返回 nil,但下次调用该方法时,您将返回一个没有存储的 PSC。
无论如何,您应该更改该方法,以便您只会返回 nil 或完全可操作的 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 - also, you mention that you would not construct your stack like this, can you let me know what is wrong with my stack? – AWillian
我发表该评论是因为您发布的代码与默认的 Xcode 核心数据模板非常相似。你调用 app-delegate 来获取目录,表明这不在 app-delegate 中,这很好。
但是,该方法表明您可以从“任何地方”懒惰地访问它,这向我表明您的堆栈不是按照我构建堆栈的方式构建的(特别是因为您还包括迁移选项)。
我并不是要暗示您所做的事情本身就是错误的,只是我不会那样做。
现在,我会第一个说我所做的就是我所做的……我不会说这是正确的方式……只是我的方式。事实上,我还没有看到其他人真正做我做的事情(我实际上是 NSManagedObjectContext 的子类,尽管我注意到警告并远离挑剔的位)。这本身可能表明我所做的可能不适合您或其他任何人。但是,我发现它适合我,以及我必须实现的相当复杂的应用程序。
那么,我将如何构建堆栈?
好吧,这比 SO 答案更深入,所以我会很简短。它还取决于堆栈的类型 - 父/子、具有相同 PSC 的 sibling 、具有不同 PSC 但相同商店的表亲。
首先,我不提供对模型和协调器的单独访问。您可以轻松地从上下文中访问它们,但它通常会导致比其值(value)更多的问题。
除了测试和简单的例子,我总是异步创建我的 MOC,就像这样......
+ (void)createWithConcurrencyType:(NSManagedObjectContextConcurrencyType)concurrencyType
completion:(void(^)(NSManagedObjectContext *moc, NSError *error))completion;
创建 MOM 并将其分配给 PSC,创建 PSC 并将其分配给 MOC。它是异步发生的,因此可能很长的打开和初始化过程可以在后台线程中完成。完成处理程序在 performBlock 中调用,因此可以干净地使用 MOC。这也可以防止在 MOC 完全设置和读取之前使用。
即使使用主队列并发类型调用,所有工作都在后台线程中完成,因此只有完成在主线程上调用。
在为导入和临时目的创建相关 MOC 时,我也使用相同的模式。
关于ios - 在 iOS9 上崩溃 -[NSPersistentStoreCoordinator _coordinator_you_never_successfully_opened_the_database_device_locked :],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33251528/