【问题标题】:CoreData error in save context, NSPersistentStoreCoordinator has no persistent stores保存上下文中的 CoreData 错误,NSPersistentStoreCoordinator 没有持久存储
【发布时间】:2013-04-08 06:18:19
【问题描述】:

我已经查看了我能找到的所有类似问题,但他们的解决方案都不适合我。

一个问题可能是,在我返回 JSON 并从 webAPI 解析之后,将实体添加到上下文(成功)和保存上下文发生在不同的线程上。但是上下文是在第一次使用 manageContext 和持久存储时设置的,如下所示。因此,在解析发生这种情况后,它将在该线程上。

确切的错误:

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

我已经尝试从模拟器中删除应用程序,正如建议的那样,没有改变。

这是我正在使用的 CoreDataHelper 类,我的应用程序中只有 1 个实例,当我在将新项目添加到上下文后调用 helper 上的 saveContext 方法时会发生错误:

@implementation CoreDataHelper

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

#pragma mark - Application's Documents directory

// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
                                                   inDomains:NSUserDomainMask] lastObject];
}

- (void)saveContext
{
    NSError *error = nil;
    if (self.managedObjectContext != nil) {
        if ([self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

- (void)dealloc {

    [self saveContext];
}

#pragma mark - Core Data stack

// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator;
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"UserGroupTV.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
                                   initWithManagedObjectModel:[self managedObjectModel]];

    // needed for lightweight migrations
    NSMutableDictionary *options = [NSMutableDictionary dictionary];
    [options setObject:[NSNumber numberWithBool:YES]
                forKey:NSMigratePersistentStoresAutomaticallyOption];
    [options setObject:[NSNumber numberWithBool:YES]
                forKey:NSInferMappingModelAutomaticallyOption];

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                   configuration:nil
                                                             URL:storeURL
                                                         options:options
                                                           error:&error])  {

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"
                                                            message:[error localizedDescription]
                                                           delegate:self
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil, nil];
        [alertView show];
    }

    return _persistentStoreCoordinator;
}


@end

ETA:我已经看到它提到过,但是如何/在哪里删除存储 sql 文件的机器上的本地文件夹?

【问题讨论】:

    标签: iphone ios objective-c core-data


    【解决方案1】:

    我没有一个明确的答案,但这里有一些事情要注意:

    1. 在您创建persistentStoreCoordinator 的位置添加一些登录信息。如果在创建过程中添加商店时发生错误,您可以在那里捕获它。

    2. 您提到您将托管对象上下文保存在后台线程上。 NSManagedObjectContext 不是线程安全的,您应该只在创建它的线程上使用特定的上下文。每个线程至少需要一个上下文。您可以观察“NSManagedObjectContextDidSaveNotification”并将更改合并到您的主要上下文中。

    【讨论】:

    • 那里有代码,如果我创建persistentStoreCoord时出现错误(商店的返回值为nil),它将弹出一个警报视图。它没有发生。
    • 检查 nil 返回并没有捕捉到这种情况。创建一个没有商店的NSPersistentStoreCoordinator 是有效的。您需要检查您的特定商店是否已添加。很可能不是。此外,我遇到此错误的唯一一次是我的应用程序在后台运行时。可能不是您的问题,但请参阅stackoverflow.com/questions/12845790/…
    【解决方案2】:

    结果我每次调用 Web API 时都在删除商店,而不是重新创建它。我最初的目标是每次用户想通过调用 api 刷新视频列表时清理数据库,我正在删除所有对象,然后删除存储并忘记重新创建它。这是我的刷新数据库方案,我只是删除了 saveContext 调用下的所有内容。

    - (void)resetDataBase {
    
        [self deleteAllObjects:@"Speaker"];
        [self deleteAllObjects:@"Tag"];
        [self deleteAllObjects:@"UserGroup"];
        [self deleteAllObjects:@"Video"];
    
        [_coreDataHelper saveContext];
    
        // REMOVED BELOW and it worked
        NSPersistentStore * store = [[_coreDataHelper.persistentStoreCoordinator persistentStores] lastObject];
        if (store) {
            NSError * error;
            [_coreDataHelper.persistentStoreCoordinator removePersistentStore:store error:&error];
            if (error) {
                [self showError:error];
            }
        }
    
        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"UserGroupTV.sqlite"];
        [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
    }
    

    【讨论】:

    • 在问题中提及这一点会很有用。 :)
    • 哈哈。我忘了问您是否在共享代码之外明确删除了商店!
    • @Mark W 我也面临着类似的问题。由于在后台线程中保存 manageContext 会发生这种情况吗?真的卡在这了……
    猜你喜欢
    • 2020-05-30
    • 2012-08-18
    • 2016-03-15
    • 2013-10-31
    • 1970-01-01
    • 2013-03-07
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多