2012-10-06 60 views
5

短的问题:当有核心数据模型的新版本确定

我只希望如果我的核心数据模型已经改变(新的实体,新的特性等)在我的应用程序运行某些代码。我怎样才能确定模型是否已经改变?

只是一些伪代码:

if (current_model_version != previous_model_version) { 
    //do some code 
    } else { 
    // do some other code 
    } 

我猜我可能会使用versionHashes要做到这一点,或isConfiguration:compatibleWithStoreMetadata :,但我不能肯定如何。

某些编辑为清楚:“目前”如“现在”和“以前”作为“最后一次应用推出。”

+1

也许[核心数据模型版本控制和数据迁移(http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreDataVersioning/Articles/Introduction.html)指南帮助。 – Rob

+0

是的,我正在挖掘它。 isConfiguration:compatibleWithStoreMetadata:为我解决了这个问题,但我需要一个实现的例子来明确它是如何使用的。 –

+0

'isConfiguration:compatibleWithStoreMetadata:'不会告诉你,有一个新的版本 - 它只会告诉你,有一个_incompatible_版本。如果你的新版本可以自动迁移,那么这将返回'是'。 _I'm只有90%肯定这一点 - 你可能不得不尝试着去证明我是对/错_ – deanWombourne

回答

8

答案似乎是isConfiguration:compatibleWithStoreMedia:

我这里找到一些有用的信息:

http://mipostel.com/index.php/home/70-core-data-migration-standard-migration-part-2

我把它这种方式:

- (BOOL)modelChanged 
{ 
    NSError *error; 
    NSURL * sourceURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"db.sqlite"]; 
    NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:sourceURL error:&error]; 
    BOOL isCompatible = [[self managedObjectModel] isConfiguration:nil compatibleWithStoreMetadata:sourceMetadata]; 

    return isCompatible; 

} 

“自我”是我的共享数据存储,而不是它一定有去那里。

deanWombourne指出,这是什么确实是决定是否可将数据自动迁移,所以它不是完全的解决我提出的问题。它在这种情况下满足我的需求。

+1

有一个输入错误 - 不要将sourcePath作为配置参数传递给isConfiguration:compatibleWithStoreMetadata:另请注意,如果商店与当前对象模型匹配,则只会返回YES,因此您无法使用它来确定商店可以迁移。您必须尝试迁移并检查错误。 – DavidA

+0

这应该返回isCompatible的逻辑反转,对吧?如果它不兼容,那是因为模型改变了,对吗? –

+1

我已将isConfiguration:sourcePath替换为isConfiguration:nil以使代码正常工作。这好像是一个错字 – sergtk

1

这是- (NSPersistentStoreCoordinator *)persistentStoreCoordinator替换代码,如果你设置在XCode的新项目时打勾的核心数据框,你得到的。

它试图打开现有源码文件(如果必要的话使用轻量级迁移)。如果失败,它将删除并重新创建商店。

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

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

    NSError *error = nil; 

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
          [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL options:options error:&error]) 
    { 
     NSLog(@"Couldn't open the store. error %@, %@", error, [error userInfo]); 

     [self deleteSqliteFilesForStore:self.storeURL]; 

     if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL options:options error:&error]) 
     { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 

      // or [NSException raise ...] 
     } 
     else 
     { 
      NSLog(@"Store deleted and recreated"); 

      // TEST DATA RE-INITIALIZATION CODE GOES HERE 
     } 
    } 
    else 
    { 
     NSLog(@"Existing Store opened successfully"); 
    } 

    return _persistentStoreCoordinator; 
} 

- (void)deleteSqliteFilesForStore:(NSURL *)storeURL 
{ 
    NSURL *baseURL = [storeURL URLByDeletingPathExtension]; 

    // Delete the associated files as well as the sqlite file 

    for (NSString *pathExtension in @[@"sqlite",@"sqlite-shm",@"sqlite-wal"]) 
    { 
     NSURL *componentURL = [baseURL URLByAppendingPathExtension:pathExtension]; 

     BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[componentURL path]]; 
     if(fileExists) 
     { 
      [[NSFileManager defaultManager] removeItemAtPath:[componentURL path] error:nil]; 
     } 
    } 
}