发布核心数据迁移

时间:2014-09-11 11:22:32

标签: iphone sqlite core-data ios7 core-data-migration

我有一个带有两个sqlite数据库和两个xcdatamodel的应用程序。所以每件事情都很好,除非我想更改或添加一些属性到其中一个模型。

我正在创建一个新的模型版本并对其进行更改。设置当前模型版本后,我启动我的应用程序并获得以下异常:

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

我的CoreData操作有以下管理器:

@interface CoreDataManager ()

@property (strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (strong, nonatomic) NSManagedObjectModel *managedObjectModel;

@property (strong, nonatomic) NSManagedObjectContext *mainQueueContext;
@property (strong, nonatomic) NSManagedObjectContext *privateQueueContext;

@end

@implementation CoreDataManager

+ (instancetype)defaultStore
{
static CoreDataManager *_defaultStore = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    _defaultStore = [self new];
});

return _defaultStore;
}

#pragma mark - Singleton Access

+ (NSManagedObjectContext *)mainQueueContextWithDB:(NSString *)db
{
return [[self defaultStore] mainQueueContextWithDB:db];
}

+ (NSManagedObjectContext *)privateQueueContextWithDB:(NSString *)db
{
return [[self defaultStore] privateQueueContextWithDB:db];
}

+ (NSManagedObjectID *)managedObjectIDFromString:(NSString *)managedObjectIDString
{
return [[[self defaultStore] persistentStoreCoordinator] managedObjectIDForURIRepresentation:[NSURL URLWithString:managedObjectIDString]];
}

#pragma mark - Lifecycle

- (id)init
{
self = [super init];
if (self) {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSavePrivateQueueContext:)name:NSManagedObjectContextDidSaveNotification object:[self privateQueueContext]];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSaveMainQueueContext:) name:NSManagedObjectContextDidSaveNotification object:[self mainQueueContext]];
}
return self;
}

- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - Notifications

- (void)contextDidSavePrivateQueueContext:(NSNotification *)notification
{
@synchronized(self) {
    [self.mainQueueContext performBlock:^{
        [self.mainQueueContext mergeChangesFromContextDidSaveNotification:notification];
    }];
}
}

- (void)contextDidSaveMainQueueContext:(NSNotification *)notification
{
@synchronized(self) {
    [self.privateQueueContext performBlock:^{
        [self.privateQueueContext mergeChangesFromContextDidSaveNotification:notification];
    }];
}
}

#pragma mark - Getters

- (NSManagedObjectContext *)mainQueueContextWithDB:(NSString *)db
{
actualDB = db;
if (!_mainQueueContext) {
    _mainQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    _mainQueueContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
}

return _mainQueueContext;
}

- (NSManagedObjectContext *)privateQueueContextWithDB:(NSString *)db
{
actualDB = db;
if (!_privateQueueContext) {
    _privateQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    _privateQueueContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
}

return _privateQueueContext;
}

#pragma mark - Stack Setup

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (!_persistentStoreCoordinator) {
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
    NSError *error = nil;

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self persistentStoreURL] options:[self persistentStoreOptions] error:&error]) {
        NSLog(@"Error adding persistent store. %@, %@", error, error.userInfo);
    }
}

return _persistentStoreCoordinator;
}

- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
    return _managedObjectModel;
}
_managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];

return _managedObjectModel;
}

- (NSURL *)persistentStoreURL
{
return [[NSFileManager appLibraryDirectory] URLByAppendingPathComponent:actualDB];
}

- (NSDictionary *)persistentStoreOptions
{
return @{NSInferMappingModelAutomaticallyOption: @YES, NSMigratePersistentStoresAutomaticallyOption: @YES};
}

@end

1 个答案:

答案 0 :(得分:0)

您可以尝试将journal_mode更改为DELETE(在iOS 7及更高版本中,猜测WAL是默认的Core Data?!?)。我使用的持久存储选项与数十个数据模型更改没有任何问题:

NSMutableDictionary *options = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                                @{@"journal_mode" : @"DELETE"}, NSSQLitePragmasOption, nil];

我希望它有所帮助...

关于http://www.sqlite.org/pragma.html上的日记帐模式:

  

“DELETE日记模式是正常行为。在DELETE模式下,每次事务结束时都会删除回滚日志。实际上,删除操作是导致事务提交的操作。(请参阅标题文档原子提交在SQLite中有更多细节。)“