将多对多关系迁移到 Core Data 中的联接表

2023-11-25

我有一个 iPhone 应用程序,它使用多对多关系将标签和注释链接在一起。我目前正在使用核心数据的“关系”功能来完成此任务,但希望迁移到使用连接表。

这是我的挑战:我想从旧模型迁移到联接表模型,并且我需要弄清楚如何执行该数据迁移。

有没有关于如何做到这一点的好例子?

更新:我在这里澄清我的问题,以帮助解决这里发生的事情:我想尝试使用辛佩瑞姆支持我们的应用程序,但 Simperium 不支持多对多关系 (!)。

作为我想要做的示例,让我们使用 iPhoneCoreDataRecipes 应用程序作为示例。

Here's what my Core Data scheme currently resembles: enter image description here

...and here's what I'm transitioning to: enter image description here

如何从一处到达另一处并携带数据?

Apple 的核心数据迁移文档非常稀疏,我没有看到任何使用 NSEntityMapping 或 NSMigrationManager 子类来完成工作的有用演练。


这是基本过程:

  1. 创建数据模型的版本化副本。 (选择模型,然后编辑器->添加模型版本)

  2. 对数据模型的新副本进行更改

  3. 将新数据模型的副本标记为当前版本。 (单击顶级 xcdatamodel 项,然后在文件检查器中将“版本化数据模型”部分下的“当前”条目设置为您在步骤 1 中创建的新数据模型。

  4. 更新模型对象以添加 RecipeIngredient 实体。还要将配方和成分实体上的成分和配方关系替换为您在步骤 2 中创建的与 RecipeIngredient 实体的新关系。 (两个实体都添加了这个关系。我称之为我的recipeIngredients)显然,无论您在旧代码中创建从成分到配方的关系,您现在都需要创建一个RecipeIngredient对象..但这超出了这个答案的范围。

  5. 在模型之间添加新的映射(文件->新文件...->(核心数据部分)->映射模型。这将为您自动生成多个映射。RecipeToRecipe、IngredientToIngredient 和 RecipeIngredient。

  6. 删除食谱成分映射。还要删除它为 RecipeToRecipe 和 IngredientToRecipe (或您在步骤 2 中调用的任何名称)提供的 RecipeIngredient 关系映射。

  7. 将 RecipeToRecipe 映射拖到映射规则列表的最后。 (这是重要的这样我们就可以确保成分在食谱之前迁移,以便我们在迁移食谱时可以将它们链接起来。)迁移将按照迁移规则列表的顺序进行。

  8. 为 RecipeToRecipe 映射“DDCDRecipeMigrationPolicy”设置自定义策略(这将覆盖 Recipes 对象的自动迁移,并为我们提供一个可以执行映射逻辑的钩子。

  9. 通过子类化食谱的 NSEntityMigrationPolicy 来覆盖 createDestinationInstancesForSourceInstance 来创建 DDCDRecipeMigrationPolicy(请参阅下面的代码)。这将为每个食谱调用一次,这将让我们创建食谱对象,以及将其链接到成分的相关食谱成分对象。我们只需让 Ingredient 通过 Xcode 在步骤 5 中自动创建的映射规则自动迁移即可。

  10. 无论您在何处创建持久对象存储(可能是 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

*覆盖 DDCDRecipeMigrationPolicy.m 中的 createDestinationInstancesForSourceInstance *

- (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 恢复器、模拟器弹跳或以上所有功能才能使其正常工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将多对多关系迁移到 Core Data 中的联接表 的相关文章

随机推荐

  • Yup 模式中的可选字段验证

    我在用着react hook form with yup用于我的表单验证并希望某些字段是可选的 空 按照他们的文档 我正在使用nullable and optional 但它仍在得到验证 export const updateAddress
  • 如何在单击按钮时从一个视图控制器导航到另一个视图控制器?

    我是 iOS 应用程序开发新手 请帮助我如何从一开始view controller到另一个view controller单击按钮时 按照以下步骤 让按钮选择器为 button addTarget select action selector
  • Android Auto - 语音 - 无法执行“在 [y] 上播放 [x]”

    我在使用 在 app 上播放 歌曲 命令时遇到问题 具体来说 Android Auto 无法识别 应用程序 我收到一条音频语音消息 不知道如何帮助在应用程序上播放歌曲 因此 语音识别工作正常 正如我所说的歌曲和应用程序一样 但是与应用程序的
  • 无法使用 OpenMPI 安装 mpi4py:无法编译 MPI 程序

    这是我在这里发表的第一篇文章 如果我的风格有误 请道歉 我一直在尝试使用 python 3 6 在 Ubuntu 16 04 上安装 mpi4py 因为 SU2 需要它进行并行处理 我下载了mpi4py并尝试从源代码构建 因为我想使用我配置
  • 如何配置 Jenkins 以在工作区中显示我的日志?

    我正在使用 Jenkins 进行 CI 并且希望能够公开日志 这样我们就不必通过 telnet 到 CI 框来查看发生了什么 有一个插件可以做到这一点吗 或者我只需要写一个脚本 我的答案是关于读取应用程序服务器 容器日志文件不同的盒子比詹金
  • Vue方法滚动div到顶部

    我在学习vue 我有以下方法 将聊天消息添加到 div 中id toolbar chat 这个 div 允许在 y 轴上滚动 我希望每次添加新消息时 div 都能跳到顶部 为什么我的 JS 不起作用 document getElementB
  • iOS 5 应用程序中对 iOS 6 功能的有条件支持

    如何在应用程序中支持 iOS6 的功能Minimal Deployment Target设置为iOS 5 0 例如 如果用户拥有 iOS 5 他将看到一个UIActionSheet 如果用户有 iOS 6 他会看到不同的UIActionSh
  • 无法转换 System.Runtime.Remoting.ObjectHandle

    在我的代码中我有一个接口 可以说它被称为InterfaceName及其实现称为InterfaceImpl 现在 当我动态尝试获取InterfaceImpl使用以下代码 object obj Activator CreateInstance
  • 如何在 Facebook 页面(不是个人资料)上发布信息到墙上

    我有一个用 php 编写的博客网站 它将新的博客文章发布到 twitter 并在后台使用使用 php curl 传递的简单 http post 请求自动进行博客 ping 我有一个博客网站的 Facebook 页面 并且希望将更新发布到页面
  • Visual 2010 不断告诉我“错误:表达式必须具有类类型”

    好吧 我需要一些见解 我正在学习 C 课程 并正在进行我的第二个项目 我正在尝试创建一个选项列表 允许您将电子邮件存储在字符串向量中 现在 在花时间帮助我并查看代码之前 我想指出我的问题 我在文件 HughesProject2 1 cpp
  • 如何进行rails外部数据库调用?

    所以我希望能够将外部数据库添加到我的config database yml然后从中建模一张表 这可能吗 我一直不知道怎么做 连接不同模型的多个数据库 连接通常通过以下方式创建ActiveRecord Base establish conne
  • Collections.emptyList() 与新实例

    在实践中 返回一个空列表是否更好this return Collections emptyList Or like this return new ArrayList
  • 将数字月份转换为月份缩写

    我有一个 csv 其中有一列名为月份的数字向量 有什么方法可以将其转换为月份的缩写月份名称吗 看看month abb持续的 例如 假设您有一个由月份组成的整数向量 那么您可以通过执行以下操作来使用它来获取月份名称的三个字母缩写 gt mon
  • 即使使用 -g 选项,GCC 也不会生成行号信息

    我已经从源代码构建并安装了 GCC 4 8 1 gcc v Using built in specs COLLECT GCC gcc COLLECT LTO WRAPPER usr local libexec gcc x86 64 unkn
  • 如何使用类型名称作为字符串来转换为类型?

    好吧 我一整天都在思考这个想法 我已经到了承认我完全不知道的程度 可能我所做的只是愚蠢的 并且有更好的方法 但这就是我的想法给我带来的 我正在尝试使用通用方法在 WinForms 中加载表单 protected void LoadForm
  • 在 Github Actions 中克隆私有存储库

    我正在尝试在 Github actions 中克隆另一个私有仓库 我已经设定SECRET USER and SECRET PASSWORD在我正在运行操作的存储库的秘密中 在操作中我正在运行命令 git clone https SECRET
  • 使用剪贴板将 Excel 数据复制到 IPython 中的 Python 列表中?

    有没有办法执行以下工作流程 选择 Excel 电子表格中的单元格 使用 Ctrl C 复制它们 将选定单元格的内容以 python 列表或 numpy 数组的形式获取到 IPython shell 中 Update 看来readline P
  • Spark - 使用 Firehose 从分区文件夹中读取 JSON

    Kinesis firehose 将文件 在本例中为时间序列 JSON 的持久性管理到按 YYYY MM DD HH 分区的文件夹层次结构 精确到 24 位数的小时 太棒了 那么如何使用 Spark 2 0 读取这些嵌套的子文件夹并从所有叶
  • JQuery 滚动/分页选项卡

    我正在尝试为一个网站创建一个简单的选项卡栏 该网站能够滚动不适合页面的选项卡 这非常简单 不需要任何 ajax 或动态加载的内容 它只是显示所有选项卡 当您单击一个选项卡时 它会将您带到另一个页面 我已经在互联网上搜索过 但似乎找不到除以下
  • 将多对多关系迁移到 Core Data 中的联接表

    我有一个 iPhone 应用程序 它使用多对多关系将标签和注释链接在一起 我目前正在使用核心数据的 关系 功能来完成此任务 但希望迁移到使用连接表 这是我的挑战 我想从旧模型迁移到联接表模型 并且我需要弄清楚如何执行该数据迁移 有没有关于如