2011-06-29 28 views
12

我在Core Data中有2個對象模型(比如v1和v2)。此遷移適用於輕量遷移。現在,我想在遷移後執行自定義代碼,但僅在遷移從v1到v2時執行。稍後如果我介紹v3,我不想讓自定義代碼得到執行。特定版本輕量級遷移後自定義代碼執行

有沒有辦法做到這一點?

由於提前, 阿努邦

+0

是否有人可以幫助我嗎? –

+0

上次我想要做這樣的事情,我最終只想做一次自定義遷移......但是如果只有最終的自定義步驟可以包含在內,那麼遷移的大部分可能是輕量級的,所以我喜歡這個問題。 賞金添加到這個問題來吸引更多的關注,看看有沒有人有這個好的答案。 –

回答

1

有可能是一個更好的辦法,買這個應該工作:

跟蹤的數據庫版本通過保持核心數據的實體名稱爲「信息」,並有名爲「CoreDataVersion」的屬性。

遷移代碼完成後,添加代碼以檢查覈心數據中的版本號。

如果「CoreDataVersion」的值爲「v1」,並且您的應用程序現在處於「v2」(可以對每個版本進行硬編碼),請執行其他自定義代碼,然後將新版本寫回數據庫。

如果你已經有「v1」發佈給用戶,只要說如果DB中沒有「CoreDataVersion」,那麼它就是「v1」。

1
- (void) _performMaintanaceUpdate:(NSUInteger) newVersion oldVersion:(NSUInteger) oldVersion { 
      if (newVersion>=1020500 && oldVersion < 1020500) { 
       NSString *storePath = [[PreferenceDataModel getDataPath] stringByAppendingPathComponent: @"wcal.sqlite"]; 
       NSFileManager *fileManager = [NSFileManager defaultManager]; 
       if ([fileManager fileExistsAtPath:storePath]) { 
         [fileManager removeItemAtPath:storePath error:NULL]; 
       } 
       [PreferenceDataModel setVersionOfLastMaintanace:newVersion]; 
      } 
} 

(void) _checkAndPerformMaintenance{ 
    NSString* strVersion = [PreferenceDataModel getApplicationVersion]; 
    //legal version is xx.xx.xx where x is a dec digit 1.2 or 1.2.33 is legit 
    NSUInteger ver = 0; 
    NSUInteger finalVer = 0; 
    int t = 3; 

    for (int i=0; i<[strVersion length]; i++) { 
     char c = [strVersion characterAtIndex:i]; 
     if (isdigit(c)) { 
      ver*=10; 
      ver+=c - 48; 
     } 
     else { 
      finalVer+= ver * pow(100, t--); 
      ver = 0; 
     } 
    } 
    finalVer+= ver * pow(100, t); 
    [self _performMaintanaceUpdate:finalVer oldVersion:[PreferenceDataModel getVersionOfLastMaintanace]]; 
} 

,這是你如何檢索應用程序版本

+(NSString *) getApplicationVersion { 
    return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 
} 
1

創建持久性存儲,做自動遷移,確定是否會遷移到2.如果您是版本之前,設置一個標誌在遷移發生後進行更改。

要確定你會被遷移,做到這一點:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"]; 
NSURL *momURL = [NSURL fileURLWithPath:path]; 
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 
NSString *version = [managedObjectModel.versionIdentifiers anyObject]; 

版本標識符在Xcode設置。

10

這裏是如何處理這種情況,基本上是使用存儲的元數據,如由蘋果工程師在2010 WWDC建議:

  • 開商店(與遷移選項)的自定義鍵
  • 檢查元數據,例如「DonePostProcessing」
  • 做後期處理...
    • 填充派生屬性
    • 插入或刪除對象
    • 集存儲元數據(「DonePostProcessing」 = YES)
  • 保存更改和元數據

更多或更少,像



- (void)loadStoreWithMigration:(NSURL *)url { 
    ... 

    store = [psc addPersistentStoreWithType: NSSQLiteStoreType configuration: nil URL: url options: opts error: &err]; 

    m = [store metadata]; 
    key = @」DonePostProcessing」; 
    if (m && ([[m objectForKey: key] integerValue] < 2)){ 
     [self doPostProcessingInContext: context]; 
     m2 = [[m mutableCopy] autorelease]; 
     [m2 setObject: [NSNumber numberWithInteger: 2] forKey: key]; 
     [store setMetadata: m2]; 

     ok = [context save:&err]; 
    } 

} 
+0

對我來說,這是一個完美的解決方案,因爲我有一個計算的字段,每當我更改算法時都需要更新。謝謝! – phatmann

0

另一種解決方案,爲我工作得好:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    NSInteger currVersion = [defaults integerForKey:@"dataModelVersion"]; 
    NSString *version = [managedObjectModel.versionIdentifiers anyObject]; 
    if (currVersion == 0) { 
     [defaults setInteger:[version integerValue] forKey:@"dataModelVersion"]; 
    } 
    else if (currVersion < [version integerValue]) { 
     NSLog(@"Migration Code"); 
     [defaults setInteger:[version integerValue] forKey:@"dataModelVersion"]; 
    }