2012-11-21 34 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)