如何重新创建persistentStore,使其不受更改.xcdatamodeld的影响

4

我希望重新创建(删除并创建)persistentStore,以防受到.xcdatamodeld的更改的影响。

我在AppDelegate中编写了以下代码持久存储协调器:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

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

    // delete if database exists
    NSError *error = nil;
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {

        // if .xcdatamodeld is changed, fail and in here...
        // if not changed, recreate success. all data removed from database

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    NSArray *stores = [_persistentStoreCoordinator persistentStores];
    for (NSPersistentStore *store in stores) {
        [_persistentStoreCoordinator removePersistentStore:store error:nil];
        [[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
    }

    // newly create database
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}

当我对.xcdatamodeld(例如,向实体添加新列)进行更改并重新启动模拟器时,第一次addPersistentStoreWithType会失败,日志显示:


Unresolved error Error Domain=NSCocoaErrorDomain Code=134100 
The operation couldn’t be completed. (Cocoa error 134100.)

我该如何做到这一点?

2个回答

1
最简单的解决方法是按照以下方式处理错误:删除您的DB文件,然后再试一次。这可以用于测试期间。
但是,如果您需要一个稳定的解决方案,请使用带有版本和自动迁移的模型:
[persistentStoreCoordinator addPersistentStoreWithType: NSSQLiteStoreType
                                         configuration: nil
                                                   URL: storeURL
                                               options: @{NSMigratePersistentStoresAutomaticallyOption : @(YES),
                                                       NSInferMappingModelAutomaticallyOption       : @(YES)}
                                                 error: &error];

此外,如果自动迁移不够用,您应该提供迁移映射。
如果你只想删除存储,可以像这样使用文件管理器:
[[NSFileManager defaultManager] removeItemAtURL: storeURL
                                          error: &error];

谢谢您的评论。如何删除我的数据库文件?我想通过上面的代码来实现,但我做不到。 - bekkou68

1

以下代码似乎对我很有效。

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

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

    // delete database if exists
    [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:nil];

    // create database
    NSError *error = nil;
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}

我在设备和模拟器中进行了以下检查:

  1. 首次启动时,应创建数据库
  2. 编辑.xcdatamodeld(添加/编辑/删除列或实体),然后重新启动,应重新创建数据库

感谢您的建议。


如果模型在启动之间发生了更改,您的解决方案将导致应用程序崩溃。 - eagle.dan.1349
啊,我明白了。但是,这仍然是过于激进的解决方案。 - eagle.dan.1349
是的,它可以工作。当然我知道这也是一种激进的方法。我会考虑在某个时候使用迁移。现在,这个解决方案对我来说已经足够了(没有用户交互数据)。无论如何,感谢您的建议 ;) - bekkou68

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接