2012-11-21 32 views
6

我有兩個模型版本 - 12和13。然後我創建了一個xcmappingmodel-文件與源12和目的地13核心數據遷移:NSEntityMigrationPolicy中的方法未被調用。

我子類NSEntityMigrationPolicy並加入我的課到mappingmodel-文件所需的實體。

@interface EndDateMigrationPolicy : NSEntityMigrationPolicy 

enter image description here

安裝和我的設備上舊版本(11)之後,我安裝與模型版本13的當前狀態 - 該應用程序運行,但我的遷移方法都不會被調用。我錯過了什麼嗎?

編輯:使用這些選項是否正確?

NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption: @YES, 
         NSInferMappingModelAutomaticallyOption: @YES}; 
+0

我有一個類似的問題。你解決了這個問題嗎?如果是,請發佈答案。 –

回答

3

我會盡力回答你,我已經經歷了很多次核心數據遷移,所以我知道它有多痛苦。對於一個你不希望必須讓你的遷移工作與這些選項,因爲你試圖做的實際上不是一個輕量級的遷移,但你告訴它做一個輕量級的遷移。

基本上讓我們說你需要某種原因有2個版本之間的非輕量級遷移,在您的案件11和12,你需要做的是做:

1-> 12輕量級 12- > 13自定義遷移 13 - >(未來版本)輕量級遷移

可能有更好的解決方案,但我還沒有找到它。

這裏有一些代碼可以幫助你(最難的部分,我不記得一切),在此代碼之前我將數據庫複製到備份,所以基本上備份數據庫是您的舊數據庫和商店是你的新的(這是空的)

NSString *path = [[NSBundle mainBundle] pathForResource:<YOUR MODEL NAME> ofType:@"cdm"]; 

NSURL *backUpURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"<YOUR MODEL NAME>MigrationBackUp.sqlite"]; //or whatever you want to call your backup 
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"<YOUR MODEL NAME>.sqlite"]; 
NSError *err2 = nil; 
NSDictionary *sourceMetadata2 = 
[NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType 
                  URL:backUpURL 
                 error:&err2]; 
NSManagedObjectModel *sourceModel2 = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:[NSBundle mainBundle]] 

                   forStoreMetadata:sourceMetadata2]; 
NSManagedObjectModel *destinationModel2 = [self managedObjectModelForVersion:@"1.4"]; //Yeah your gonna have to get your mapping model , I'll give you this code too later 
NSString *oldModel = [[sourceModel2 versionIdentifiers] anyObject]; 
NSLog(@"Source Model : %@",oldModel); 
NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]]; 

if (mappingModel != nil) { 
    for (NSString * identifier in [mappingModel entityMappings]) { 
     NSLog(@"Mapping > %@",identifier); 
    } 
} 

然後,只需創建一個包含源和目標的遷移器。

這也是事後困難的部分:

BOOL success = [migrator migrateStoreFromURL:backUpURL 
             type:NSSQLiteStoreType 
            options:nil 
          withMappingModel:mappingModel 
          toDestinationURL:storeURL 
          destinationType:NSSQLiteStoreType 
          destinationOptions:nil 
             error:&err2]; 

最後但並非最不重要(我說我之前給你):

- (NSManagedObjectModel *)managedObjectModelForVersion:(NSString*)version { 

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"]; 
if (BETWEEN_INEX(version, @"1.0", @"1.4")) { 
    modelPath = [modelPath stringByAppendingPathComponent:@"Model"]; 
    modelPath = [modelPath stringByAppendingPathExtension:@"mom"]; 
} else if (BETWEEN_INEX(version, @"1.4", @"1.5")) { 
    modelPath = [modelPath stringByAppendingPathComponent:@"Model 2"]; 
    modelPath = [modelPath stringByAppendingPathExtension:@"mom"]; 
} else if (BETWEEN_INEX(version, @"1.5", @"1.6")) { 
    modelPath = [modelPath stringByAppendingPathComponent:@"Model 3"]; 
    modelPath = [modelPath stringByAppendingPathExtension:@"mom"]; 
} else if (BETWEEN_INEX(version, @"1.6", @"1.7")) { 
    modelPath = [modelPath stringByAppendingPathComponent:@"Model 4"]; 
    modelPath = [modelPath stringByAppendingPathExtension:@"mom"]; 
} 
NSURL *modelURL = [NSURL fileURLWithPath:modelPath]; 
NSManagedObjectModel * oldManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
NSSet *vIdentifiers = [oldManagedObjectModel versionIdentifiers]; 
for (NSString * identifier in vIdentifiers) { 
    NSLog(@"Old Model : %@",identifier); 
} 
return [oldManagedObjectModel autorelease]; 

}

我知道這些只是代碼片段,但我真的希望它可以幫助你解決你的問題,如果你需要其他任何東西只是問。

+0

這真的是最好的方法嗎?是不是更容易「混合」輕量級和複雜的遷移? – swalkner

+0

我很確定這是最簡單的方法。遷移模型只能引用2個模式版本。複雜的部分並不是真正的混合遷移,這很簡單,你只需要連續進行,複雜的遷移就是困難所在。 – thewormsterror

1

不會被調用你的NSEntityMigrationPolicy因爲你設置NSInferMappingModelAutomaticallyOption到@(YES) - 它應該是@(NO)