2008-12-19 61 views
4

我的基于Core Data文档的应用程序(仅限10.5)的数据模型位于 框架中,因此使用核心数据映射 模型进行自动模式升级似乎不起作用。核心数据机构 似乎没有在 不在应用的主包中找到适当的数据模型或映射模型。因此,我正在运行 configurePersistentStoreCoordinatorForURL:ofType:...我的 NSPersistenDocument子类(以下代码)手动执行迁移,而不是使用自动迁移 。如果 迁移成功,我将永久存储 存储迁移到临时文件,然后覆盖现有文件。该文档然后显示 消息出现错误“自打开或保存该文档后,该文档的文件已被其他应用程序 更改。”当我尝试保存时。正如其他 列表中指出的那样,这是由于我修改了 文档的“背后”。我尝试更新文档的 文件修改日期,如下所示,但是我随后收到一条错误对话框 ,并提示“文档的位置”test.ovproj“不能被确定为 ”。当我尝试保存时。我不太确定这个 错误的原因,但在其他 交易一个不必要的消息(在这种情况下)是不是我想要的。没有“文档更改”警告的手动核心数据模式迁移?

任何人都可以提供一些指导?有没有办法手动升级 模式的文件的持久存储没有触发 这些(这个这种情况下不必要的)警告之一?在我的子类 -configurePersistentStoreCoordinatorForURL:ofType:...升级数据存储

代码:

if(upgradeNeeded) { 
      NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:VUIModelBundles() orStoreMetadata:meta]; 

      if(sourceModel == nil) { 
       *error = [NSError errorWithDomain:VUIErrorDomainn ode:VUICoreDataErrorCode localizedReason:BWLocalizedString(@"Unable to find original data model for project.")]; 
       return NO; 
      } 

      NSManagedObjectModel *destinationModel = [self managedObjectModel]; 

      NSMigrationManager *migrationManager = [[NSMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:destinationModel]; 
      NSMappingModel *mappingModel = [NSMappingModel mappingModelFromBundles:VUIModelBundles() forSourceModel:sourceModel destinationModel:destinationModel]; 
      if(mappingModel == nil) { 
       *error = [NSError errorWithDomain:VUIErrorDomain code:VUICoreDataErrorCode localizedReason:BWLocalizedString(@"Unable to find mapping model to convert project to most recent project format.")]; 
       return NO; 
      } 

      @try { 
       //move file to backup 
       NSAssert([url isFileURL], @"store url is not a file URL"); 

       NSString *tmpPath = [NSString tempFilePath]; 
       id storeType = [meta objectForKey:NSStoreTypeKey]; 
       if(![migrationManager migrateStoreFromURL:url 
                type:storeType 
               options:storeOptions 
             withMappingModel:mappingModel 
             toDestinationURL:[NSURLfileURLWithPath:tmpPath] 
             destinationType:storeType 
             destinationOptions:storeOptions 
                error:error]) { 

        return NO; 
       } else { 
        //replace old with new 
        if(![[NSFileManager defaultManager] removeItemAtPath:[url path] error:error] || 
         ![[NSFileManager defaultManager] moveItemAtPath:tmpPath toPath:[url path] error:error]) { 
         return NO; 
        } 

        // update document file modification date to prevent warning (#292) 
        NSDate *newModificationDate = [[[NSFileManager defaultManager] fileAttributesAtPath:[url path] traverseLink:NO] bjectForKey:NSFileModificationDate]; 
        [self setFileModificationDate:newModificationDate]; 
       } 
      } 
      @finally { 
       [migrationManager release]; 
      } 
     } 
    } 

    return [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:storeOptions error:error]; 

回答

1

我还没有碰到过这种特定情况下运行,但我有一些猜测。首先,而不是使用-removeItemAtPath:和-moveItemAtPath:当您要切换文件时,请改用FSExchangeObjects()函数。 NSDocument使用FSRefs来跟踪文件,除非您使用FSExchangeObjects(),否则它会意识到它正在查看完全不同的文件。其次,您可以通过重写-managedObjectModel来手动设置文档的托管对象模型,特别是使用+ mergedModelFromBundles:方法从框架中加载模型。根据文档,它应该默认合并主包和所有链接框架中的任何模型,所以这只适用于动态加载的包。不知道为什么这不适合你,但我没有尝试过。为了找出要搜索的捆绑包,NSBundle的+ bundleForClass:方法是你的朋友。

+0

甚至在设置文件修改日期之前设置文件修改日期有趣的是,readFromURL:ofType:error:并未解决问题。使用FSExchangeObjects(),以及使用[self setFileModificationDate:]和新文件修改日期确实有效。感谢指针。 – 2008-12-23 23:47:52

1

当心FSExchangeObjects()!它不支持所有卷类型,请参阅bSupportsFSExchangeObjects。我正在寻找替代品。选项似乎是MoreFilesX的FSExchangeObjectsCompat或10.5的FSReplaceObjects()。

0

10年后... 我遇到了同样的问题,并与NSDocument新的API,你可以以后做迁移

migrate() 
if let newModificationDate = try? NSFileManager.defaultManager().attributesOfItemAtPath(url.path!)[NSFileModificationDate] as? NSDate { 
    self.fileModificationDate = newModificationDate 
} 

后更新的文件新的日期更新文档的fileModificationDate你可以叫super.configurePersistentStoreCoordinatorForURL...

这是因为NSDocument甚至在致电readFromURL:ofType 请参阅Document Initialization Message Flow