如何在不复制目标 NSManagedObject 的情况下将目标 NSManagedObject 添加到另一个具有反向多对多核心数据关系的对象?
How to Add target NSManagedObject to another one with an inverse many-to-many Core Data relationship without duplicating target NSManagedObject?
我在我的一个项目中遇到了一个问题,我花了几十个小时来寻找解决方案,我取得了一些进展,但仍然没有达到我想要达到的理想状态。我现在仍在寻找解决方案,但我真的很感激任何人都可以分享任何关于建设性解决方案的见解。
问题:
- 如何将主列表中的目标 NSManagedObject 添加为一个对象
另一个 NSManagedObject 中的引用
每个 NSManagedObject 之间没有多对多关系
在主列表中创建重复的目标 NSManagedObject。
注:
- 以下示例使用了对完整数据模型图的类比
到我的真实项目。这个类比是我最能描述问题的
我有,而类比中的对象并不完全相同
实际项目中对象的名称。
我现在拥有的:
成分对象的主列表,每个对象都是唯一的
其他.
菜谱对象列表,每一个都希望有不同的
配料对象来定义配方对象。
我想达到什么目的:
成分对象可以多次插入到单个配方对象中,每次插入都作为唯一计数,而不是将相同成分视为一个单一计数。
我不想复制
主列表能够向每个添加多个成分对象
配方对象或交叉多个配方对象。
我试过的:
使用Core Data管理食材和配方为2
NS 管理对象。
在成分管理对象上创建了一个名为“allHostRecipes”的关系属性,并将其设置为与食谱管理对象的“对多”关系
在配方管理对象上创建了一个名为“allUsedIngredients”的关系属性,并将其设置为与成分管理对象的“对多”关系。
- 这两个关系设置为“反向”。
- 我有一个食谱描述视图,其中包含一个 Table 视图,其中列出了所有现在和将要包含在食谱中的成分。
- 我创建了另一个成分选择 Table 视图,可以在配方描述视图中触发该视图以选择将要添加到配方中的每种成分。
- 每次在 Ingredients Selection Table 视图中选择一种成分时,我在 NSFetchedResultsController 上调用 objectAtIndexPath(_:) 用于成分 Table 从成分的主列表查看在其 ManagedObjectContext 中找到选定的成分对象。
然后我将选定的成分管理对象 (SelectedIngredientManagedObject) 传回食谱描述视图,并在 NSFetchedResultsController 上调用 mutableSetValueForKey("allUsedIngredients").addObject(SelectedIngredientManagedObject) 用于获取成分包含在配方对象中。
“用于成分 Table 从成分主列表查看的 NSFetchedResultsController”和“用于获取包含在食谱对象中的成分的 NSFetchedResultsController”是单独的实例“Table 配方描述视图视图”和“成分选择 Table 视图”中的变量。但他们引用了相同的 ManagedObjectContext。
我现在得到的是:
- 选择的配料管理对象可以添加到食谱中。
- 但是,如果我多次选择相同的成分,它只会在 Table 配方描述视图的视图中计数一次,而不是每次插入时显示多个计数,这不是我想要实现的如上所述。
我的问题:
- 我应该怎么做或调整才能实现我拥有的功能
上面描述?
我认为解决问题的方向:
- 在定义“多对多”时我还应该做什么
核心数据模型中的关系?
- “对多”引用使用 NSSet 的事实是否会导致计数问题?
- 是否需要创建多个ManagedObjectContext 来实现所需的功能?
- 我是否应该将选定的成分管理对象克隆为新的成分管理对象?我试过,它会将重复的成分添加到成分的主列表中。这也不是我想要的。如果我需要克隆它,我怎样才能正确?
非常感谢您花时间查看它,期待您的见解。非常感谢。
此致,
骑士
你需要稍微改造一下数据:去掉Recipe
到Ingredient
的多对多关系,换成中间实体(找个好名字很难,比方说RecipeIngredientDetails
).
创建一个从 Recipe
到 RecipeIngredientDetails
的一对多关系,比如 allUsedIngredientDetails
,反向(一对一)recipe
。
同样创建一个从 Ingredient
到 RecipeIngredientDetails
的一对多关系,比如 allHostRecipeDetails
,反向(一对一)ingredient
。
这解决了直接多对多关系的问题,其中每个 Recipe
只能与每个 Ingredient
相关一次。 (你是对的,这部分是因为关系被建模为集合,不能有重复的成员)。您有两个选择:您可以只添加多个 RecipeIngredientDetails
对象,每个对象都与相同的 Recipe
和 Ingredient
对相关。每个这样的对象可能代表成分的标准基本数量。请注意,每个 Recipe
/Ingredient
对不能只有一个对象,并尝试多次将该对象添加到同一个 Recipe
:一个给定的 Recipe
和一个给定 RecipeIngredientDetails
个对象最多可以关联一次。
但是向 RecipeIngredientDetails
添加一个属性可能会更好,比如 quantity
。然后,每个 Recipe
/Ingredient
对只需要一个这样的对象,并且可以更新 quantity
属性以反映适合该食谱的配料量。
这是 Modeling a Relationship Based on Its Semantics 上的 CoreData 编程指南部分中提到的方法:
For this sort of relationship, use an intermediate (join) entity. An advantage of the intermediate entity is that you can also use it to add more information to the relationship.
相当于在SQL 数据库中添加一个带有外键和附加列的连接table。我不知道有任何更简单的方法可以在 CoreData 中实现您的目标 - 无法直接向关系添加属性。
关于您在评论中提到的排序问题,您已添加"a Double type attribute in the Entity to keep track of the order"。如果您只有两个实体和多对多关系,并且将顺序属性添加到 Ingredient
,那么(例如)如果 "Flour" 是 "Bread" 的第一个成分,它必须是使用它的每个其他食谱的第一项。在我描述的方法中,您可以将属性添加到中间实体,RecipeIngredientDetails
:索引(就像数量一样)取决于 配方和原料。
然而,对于索引,我应该提到另一个选项:您可以(在数据模型编辑器中)将 Recipe 到 RecipeIngredientDetails
的关系定义为 ordered .生成的 属性 将是一个有序集(因此您可以插入、删除或移动项目以实现正确的顺序)。
我在我的一个项目中遇到了一个问题,我花了几十个小时来寻找解决方案,我取得了一些进展,但仍然没有达到我想要达到的理想状态。我现在仍在寻找解决方案,但我真的很感激任何人都可以分享任何关于建设性解决方案的见解。
问题:
- 如何将主列表中的目标 NSManagedObject 添加为一个对象 另一个 NSManagedObject 中的引用 每个 NSManagedObject 之间没有多对多关系 在主列表中创建重复的目标 NSManagedObject。
注:
- 以下示例使用了对完整数据模型图的类比 到我的真实项目。这个类比是我最能描述问题的 我有,而类比中的对象并不完全相同 实际项目中对象的名称。
我现在拥有的:
成分对象的主列表,每个对象都是唯一的
其他.菜谱对象列表,每一个都希望有不同的 配料对象来定义配方对象。
我想达到什么目的:
成分对象可以多次插入到单个配方对象中,每次插入都作为唯一计数,而不是将相同成分视为一个单一计数。
我不想复制 主列表能够向每个添加多个成分对象 配方对象或交叉多个配方对象。
我试过的:
使用Core Data管理食材和配方为2 NS 管理对象。
在成分管理对象上创建了一个名为“allHostRecipes”的关系属性,并将其设置为与食谱管理对象的“对多”关系
在配方管理对象上创建了一个名为“allUsedIngredients”的关系属性,并将其设置为与成分管理对象的“对多”关系。
- 这两个关系设置为“反向”。
- 我有一个食谱描述视图,其中包含一个 Table 视图,其中列出了所有现在和将要包含在食谱中的成分。
- 我创建了另一个成分选择 Table 视图,可以在配方描述视图中触发该视图以选择将要添加到配方中的每种成分。
- 每次在 Ingredients Selection Table 视图中选择一种成分时,我在 NSFetchedResultsController 上调用 objectAtIndexPath(_:) 用于成分 Table 从成分的主列表查看在其 ManagedObjectContext 中找到选定的成分对象。
然后我将选定的成分管理对象 (SelectedIngredientManagedObject) 传回食谱描述视图,并在 NSFetchedResultsController 上调用 mutableSetValueForKey("allUsedIngredients").addObject(SelectedIngredientManagedObject) 用于获取成分包含在配方对象中。
“用于成分 Table 从成分主列表查看的 NSFetchedResultsController”和“用于获取包含在食谱对象中的成分的 NSFetchedResultsController”是单独的实例“Table 配方描述视图视图”和“成分选择 Table 视图”中的变量。但他们引用了相同的 ManagedObjectContext。
我现在得到的是:
- 选择的配料管理对象可以添加到食谱中。
- 但是,如果我多次选择相同的成分,它只会在 Table 配方描述视图的视图中计数一次,而不是每次插入时显示多个计数,这不是我想要实现的如上所述。
我的问题:
- 我应该怎么做或调整才能实现我拥有的功能 上面描述?
我认为解决问题的方向:
- 在定义“多对多”时我还应该做什么 核心数据模型中的关系?
- “对多”引用使用 NSSet 的事实是否会导致计数问题?
- 是否需要创建多个ManagedObjectContext 来实现所需的功能?
- 我是否应该将选定的成分管理对象克隆为新的成分管理对象?我试过,它会将重复的成分添加到成分的主列表中。这也不是我想要的。如果我需要克隆它,我怎样才能正确?
非常感谢您花时间查看它,期待您的见解。非常感谢。
此致,
骑士
你需要稍微改造一下数据:去掉Recipe
到Ingredient
的多对多关系,换成中间实体(找个好名字很难,比方说RecipeIngredientDetails
).
创建一个从 Recipe
到 RecipeIngredientDetails
的一对多关系,比如 allUsedIngredientDetails
,反向(一对一)recipe
。
同样创建一个从 Ingredient
到 RecipeIngredientDetails
的一对多关系,比如 allHostRecipeDetails
,反向(一对一)ingredient
。
这解决了直接多对多关系的问题,其中每个 Recipe
只能与每个 Ingredient
相关一次。 (你是对的,这部分是因为关系被建模为集合,不能有重复的成员)。您有两个选择:您可以只添加多个 RecipeIngredientDetails
对象,每个对象都与相同的 Recipe
和 Ingredient
对相关。每个这样的对象可能代表成分的标准基本数量。请注意,每个 Recipe
/Ingredient
对不能只有一个对象,并尝试多次将该对象添加到同一个 Recipe
:一个给定的 Recipe
和一个给定 RecipeIngredientDetails
个对象最多可以关联一次。
但是向 RecipeIngredientDetails
添加一个属性可能会更好,比如 quantity
。然后,每个 Recipe
/Ingredient
对只需要一个这样的对象,并且可以更新 quantity
属性以反映适合该食谱的配料量。
这是 Modeling a Relationship Based on Its Semantics 上的 CoreData 编程指南部分中提到的方法:
For this sort of relationship, use an intermediate (join) entity. An advantage of the intermediate entity is that you can also use it to add more information to the relationship.
相当于在SQL 数据库中添加一个带有外键和附加列的连接table。我不知道有任何更简单的方法可以在 CoreData 中实现您的目标 - 无法直接向关系添加属性。
关于您在评论中提到的排序问题,您已添加"a Double type attribute in the Entity to keep track of the order"。如果您只有两个实体和多对多关系,并且将顺序属性添加到 Ingredient
,那么(例如)如果 "Flour" 是 "Bread" 的第一个成分,它必须是使用它的每个其他食谱的第一项。在我描述的方法中,您可以将属性添加到中间实体,RecipeIngredientDetails
:索引(就像数量一样)取决于 配方和原料。
然而,对于索引,我应该提到另一个选项:您可以(在数据模型编辑器中)将 Recipe 到 RecipeIngredientDetails
的关系定义为 ordered .生成的 属性 将是一个有序集(因此您可以插入、删除或移动项目以实现正确的顺序)。