我已经得到了使用许多一对多关系链接标签和注释在一起的iPhone应用程序。 我目前使用的核心数据的“关系”功能来做到这一点,但想迁移到使用一个连接表来代替。
这里是我的挑战:我想从旧模式向加盟表模型迁移,以及我需要弄清楚如何执行数据迁移。
是否有一个如何做到这一点任何很好的例子?
更新:我在这里澄清,我的问题,以帮助什么是怎么回事:我想用尽量Simperium来支持我们的应用程序,但Simperium不支持许多一对多的关系(!)。
至于是什么,我试图做一个例子,让我们使用iPhoneCoreDataRecipes应用作为例子。
下面是我的核心数据方案目前类似:
...这里就是我过渡到:
我如何从一个到另一个,和我一起把数据?
苹果的核心数据迁移文档是出了名的稀疏,我看不出任何有用的演练了使用NSEntityMapping或NSMigrationManager子类来完成这项工作。
这里的基本过程是:
创建数据模型的版本副本。 (选择型号,然后编辑 - >添加示范文本)
进行更改数据模型的新副本
标志着新的数据模型的副本作为当前版本。 (点击顶级xcdatamodel项目,然后在文件检查器中设置下“版本的数据模型”部分的“当前”进入您在步骤1中创建新的数据模型。
更新你的模型对象添加RecipeIngredient实体。 同时更换原料和配方上的食谱关系,并与您在步骤2到RecipeIngredient实体创建新的关系成分的实体。 (这两个实体获得这种关系增加。我打电话给我recipeIngredients)显然,无论你在旧代码创建成分配方的关系,你现在需要创建一个RecipeIngredient对象..但已经超出了这个答案的范围。
添加车型之间的新映射(文件 - >新建文件...->(核心数据段) - >映射模型这将自动为您生成几个映射RecipeToRecipe,IngredientToIngredient和RecipeIngredient。
删除RecipeIngredient映射。 还删除recipeIngredient关系映射它给你RecipeToRecipe和IngredientToRecipe(或任何你叫他们在步骤2中)。
拖动RecipeToRecipe映射是最后的映射规则列表中。 (因此,我们相信该成分的配方之前迁移,使我们可以当我们迁移的食谱他们连接起来这是非常重要的 。)迁移将在迁移规则列表的顺序去。
设置自定义策略的RecipeToRecipe映射“DDCDRecipeMigrationPolicy”(这将覆盖配方对象的自动迁移,并给我们一个钩子,我们可以执行映射逻辑。
通过继承NSEntityMigrationPolicy食谱覆盖createDestinationInstancesForSourceInstance创建DDCDRecipeMigrationPolicy(见下面的代码)。 这一次,每个配方被调用,这将让我们创建配方对象,同时也将其链接的相关RecipeIngredient对象成分。 我们只要让成分被自动通过Xcode的汽车在第5步中为我们创建的映射规则迁移。
无论你创建你的持久化对象存储(可能的AppDelegate),确保您设置的用户词典自动迁移数据模型:
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, nil]
error:&error])
{
}
子类NSEntityMigrationPolicy食谱
#import <CoreData/CoreData.h>
@interface DDCDRecipeMigrationPolicy : NSEntityMigrationPolicy
@end
* 覆盖createDestinationInstancesForSourceInstance在DDCDRecipeMigrationPolicy.m *
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error
{
NSLog(@"createDestinationInstancesForSourceInstance : %@", sInstance.entity.name);
//We have to create the recipe since we overrode this method.
//It's called once for each Recipe.
NSManagedObject *newRecipe = [NSEntityDescription insertNewObjectForEntityForName:@"Recipe" inManagedObjectContext:[manager destinationContext]];
[newRecipe setValue:[sInstance valueForKey:@"name"] forKey:@"name"];
[newRecipe setValue:[sInstance valueForKey:@"overview"] forKey:@"overview"];
[newRecipe setValue:[sInstance valueForKey:@"instructions"] forKey:@"instructions"];
for (NSManagedObject *oldIngredient in (NSSet *) [sInstance valueForKey:@"ingredients"])
{
NSFetchRequest *fetchByIngredientName = [NSFetchRequest fetchRequestWithEntityName:@"Ingredient"];
fetchByIngredientName.predicate = [NSPredicate predicateWithFormat:@"name = %@",[oldIngredient valueForKey:@"name"]];
//Find the Ingredient in the new Datamodel. NOTE!!! This only works if this is the second entity migrated.
NSArray *newIngredientArray = [[manager destinationContext] executeFetchRequest:fetchByIngredientName error:error];
if (newIngredientArray.count == 1)
{
//Create an intersection record.
NSManagedObject *newIngredient = [newIngredientArray objectAtIndex:0];
NSManagedObject *newRecipeIngredient = [NSEntityDescription insertNewObjectForEntityForName:@"RecipeIngredient" inManagedObjectContext:[manager destinationContext]];
[newRecipeIngredient setValue:newIngredient forKey:@"ingredient"];
[newRecipeIngredient setValue:newRecipe forKey:@"recipe"];
NSLog(@"Adding migrated Ingredient : %@ to New Recipe %@", [newIngredient valueForKey:@"name"], [newRecipe valueForKey:@"name"]);
}
}
return YES;
}
我会发布在Xcode中设置及样品Xcode项目的图片,但我似乎并没有对堆栈溢出还没有任何信誉分...所以它不会让我。 我会后这对我的博客也是如此。 bingosabi.wordpress.com/。
还要注意的是,Xcode的核心数据模型映射的东西是有点片状,偶尔需要一个“干净”的,良好的Xcode RESTER,模拟器反弹或以上所有的都搞不定。
正如我在关于这一问题的意见建议,你可能不希望改变你的数据模型,而是创建模型和不理解许多一对多关系库之间的桥梁。
要创建的连接表,实际上是已经在那里,你只需要另一种方式来您的数据提供给该库。
这是否能正常工作,取决于这个库如何看待你的模型。 有它不同的方式来查询您的实体的属性,或者它可能是你是一个指定哪些属性/关系被复制。
这很难给出一个真正的答案,而对所有这一切的任何细节,但总的想法是:
你有头看起来像一些管理的对象:
// Recipe.h
@interface Recipe : NSManagedObject
@property (nonatomic,retain) NSSet *ingredients;
@end
现在你到这个对象的一些额外的方法,使用类别:
// Recipe+fakejoin.h
@interface Recipe (fakejoin)
-(NSSet*)recipeIngredients;
@end
和在一个实施Recipe+fakejoin.m
此方法,它返回一个的NSSet
与RecipeIngredients
对象。
但正如我所说,这是一个开放的问题,如果这个库可以让你玩这样不会破坏东西。 如果这一切听起来新的给你,还是另找一个解决方案...