正确访问核心数据中建模的类的属性的方法

时间:2013-05-08 20:11:19

标签: ios objective-c cocoa core-data

假设一个Recipe对象的NSSetIngredientrecipe,并且相同的关系在核心数据中建模。

鉴于recipe.ingredients,访问其成分的正确方法是什么?

在此示例中,使用NSFetchRequest似乎很自然,但我可以同样使用Ingredient NSPredicate个实体{{1}}来匹配配方。

现在让我们说我只想要'收集'的成分。这对我来说不太明确 - 我应该使用带有谓词限制配方和收集状态的成分的获取请求吗?或者循环通过recipe.ingredients?

在规模的另一端,也许我只需要来自这个配方的成分也会出现在其他配方中。现在,获取请求似乎更具吸引力。

正确的一般方法是什么?或者是个案情况?我对以下方面的影响感兴趣:

  1. Consitancy
  2. 可读性
  3. 性能
  4. 健壮性(例如,在编译器无法捕获的获取请求中很容易出错)。

3 个答案:

答案 0 :(得分:1)

让我们按顺序完成这些。

  1. 获取特定Recipe的成分时,如果您已有参考:每次都使用recipe.ingredients

  2. 获取具有特定值的特定Recipe的成分(例如布尔标志值):最简单的可能是从上面的recipe.ingredients开始,然后使用类似{{{ 1}} NSSet来过滤它们。最优雅的是在objectsPassingTest上设置一个fetched属性,只返回这些成分而不需要额外的代码(语法可能不会立即明显,有关详细信息,请参阅a previous answer I wrote)。这两个可能表现相同。最不吸引人的是获取请求。

  3. 获取出现在多个配方实例中的成分:可能是Recipe实体的获取请求,其中谓词类似于Ingredientrecipe in %@被替换为%@ Recipe个实例列表。

答案 1 :(得分:1)

一些基本信息:

*内存操作比磁盘操作快约100-1000倍 *获取请求执行始终是商店(磁盘)的行程,因此会降低性能。

在您的情况下,您需要查询一组“小”对象以获取信息 只需使用recipe.ingredients迭代它们就会逐个错误,每次访问都是商店之旅(故障解决)。

在这种情况下,请使用预取(在请求中,设置setRelationshipKeyPathsForPrefetching:以预取ingredients关系或执行获取具有相应谓词的集合的获取请求。)

如果您只需要特定数据,请使用获取请求方法仅检索您需要的数据。

如果您打算重复访问查询和信息的关系,只需使用预取来获取整个集合,然后在内存中查询。

我的观点是:

考虑最小化磁盘访问的方法(在任何情况下,您至少需要1次访问)。
如果您的数据太大而无法存储在内存中,或者要在内存中查询,请执行提取以仅获取所需的数据。

现在:
1.Consistency - 选择一种你觉得舒服并坚持使用的方法(我使用预取)
2.Readability - 使用属性比执行查询更具可读性,但是如果不使用预取则效率较低。
3.性能 - 磁盘访问会降低性能,但在某些情况下是不可避免的 4.Robustness - 获取请求表明您知道什么是最适合您的数据使用。明智地使用它。

要确保最大限度地减少磁盘访问,请启用SQLite调试
(-com.apple.CoreData.SQLDebug)

编辑:

Faulting behaviour

答案 2 :(得分:0)

  

在这个例子中,使用recipe.ingredients似乎很自然,但是我   同样可以使用NSFetchRequest for Ingredient实体   NSPredicate按配方匹配。

当你能做前者时,你为什么要做后者?你已经拥有了这个配方,它已经有了一套配料,所以不需要查看所有成分,只过滤那些与你已经拥有的食谱相关的成分。

  

现在让我们说我只想要'收集'的成分。这个   对我不太清楚 - 我应该使用成分的取指令   用谓词限制配方和收集状态?或循环   通过recipe.ingredients?

将谓词应用于食谱的成分:

NSPredicate *isCollected = [NSPredicate predicateWithFormat:@"collected == YES"];
NSSet *collectedIngredients = [recipe.ingredients filteredSetUsingPredicate:isCollected];
  

在规模的另一端,也许我只需要来自的成分   这个食谱也出现在其他食谱中。现在,获取请求   似乎更有吸引力。

同样,在这里使用获取请求似乎很浪费,因为您已经可以轻松访问可能在最终结果中的成分集,并且这可能比所有成分的集合小得多。使用与上述相同的方法,但更改谓词以测试与每种成分相关的配方。类似的东西:

NSPredicate *p = [NSPredicate predicateWithFormat:@"recipes > 1"];
NSSet *i = [recipe.ingredients filteredSetUsingPredicate:p];
  

正确的一般方法是什么?

获取请求是搜索给定实体的所有实例的好方法。您总是使用获取请求启动以获取一些对象。但是当你想要的对象以某种方式与你已经拥有的对象相关时,你可以(并且应该)使用这些关系来获得你想要的东西。