jjzjj

ios - 在 iOS9 上崩溃 -[NSPersistentStoreCoordinator _coordinator_you_never_successfully_opened_the_database_device_locked :]

coder 2023-09-25 原文

我的应用最近因 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/

有关ios - 在 iOS9 上崩溃 -[NSPersistentStoreCoordinator _coordinator_you_never_successfully_opened_the_database_device_locked :]的更多相关文章

随机推荐