2008-12-19 59 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