确定核心数据模型何时有新版本

Posted

技术标签:

【中文标题】确定核心数据模型何时有新版本【英文标题】:Determining when there are new versions in core data model 【发布时间】:2012-10-06 01:26:54 【问题描述】:

小问题:

仅当我的核心数据模型发生更改(新实体、新属性等)时,我才想在我的应用程序中运行特定代码。如何确定模型是否已更改?

只是一些伪代码:

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

我猜我可能会使用 versionHashes 或 isConfiguration:compatibleWithStoreMetadata:,但我不确定如何。

为清晰起见进行了一些编辑:“当前”与“现在”相同,“以前”与“上次启动应用程序”相同。

【问题讨论】:

也许Core Data Model Versioning and Data Migration 指南会有所帮助。 是的,我正在研究它。 isConfiguration:compatibleWithStoreMetadata: 为我解决了这个问题,但我需要一个实现示例来准确了解它的使用方式。 isConfiguration:compatibleWithStoreMetadata: 不会告诉你有一个新版本 - 它只会告诉你有一个 incompatible 版本。如果您的新版本可以自动迁移,那么这将返回YES我对此只有 90% 的把握——你可能需要通过实验来证明我的正确/错误! 你说得对。对我来说,第二部分是设置数据迁移。我正在开发的应用程序根据特定标准对设备上的歌曲进行分类,并将分类数据存储在核心数据中。之前开发它的开发人员只需清空数据库并在每次应用程序版本更改时重新分类所有歌曲,无论数据库是否更改。我正在设置它,这样我就不必在每次应用版本更改时对数据进行分类,并且迁移数据是自然的下一步。 【参考方案1】:

答案似乎是 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;


'self' 是我的共享数据存储,不一定非要去那里。

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

【讨论】:

那里有一个错字 - 不要将 sourcePath 作为配置参数传递给 isConfiguration:compatibleWithStoreMetadata: 另请注意,如果商店与当前对象模型匹配,这只会返回 YES,所以你不能使用这个来确定可以迁移的商店。您必须尝试迁移并检查错误。 这应该是返回 isCompatible 的逆逻辑,对吧?如果不兼容,那是因为型号变了,对吗? 我已将 isConfiguration:sourcePath 替换为 isConfiguration:nil 以使代码正常工作。好像是错别字 好的,谢谢。有一段时间没有使用此代码了。不会抓住它。【参考方案2】:

这是- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 的替换代码,如果您在 XCode 中设置新项目时勾选核心数据框,您将获得该代码。

它会尝试打开现有的 sqlite 文件(必要时使用轻量级迁移)。如果失败,它会删除并重新创建商店。

- (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];
        
    

【讨论】:

以上是关于确定核心数据模型何时有新版本的主要内容,如果未能解决你的问题,请参考以下文章

向核心数据实体添加瞬态属性是不是需要新版本模型?

修改核心数据模型每次都需要新版本?

更新了核心数据模型,没有新版本,如何修复?

在新版本的应用程序中替换核心数据模型,无需以前的源代码

CoreData:用新版本替换数据模型?

核心数据模型版本控制和数据迁移