假设一个Recipe
对象的NSSet
为Ingredient
个recipe
,并且相同的关系在核心数据中建模。
鉴于recipe.ingredients
,访问其成分的正确方法是什么?
在此示例中,使用NSFetchRequest
似乎很自然,但我可以同样使用Ingredient
NSPredicate
个实体{{1}}来匹配配方。
现在让我们说我只想要'收集'的成分。这对我来说不太明确 - 我应该使用带有谓词限制配方和收集状态的成分的获取请求吗?或者循环通过recipe.ingredients?
在规模的另一端,也许我只需要来自这个配方的成分也会出现在其他配方中。现在,获取请求似乎更具吸引力。
正确的一般方法是什么?或者是个案情况?我对以下方面的影响感兴趣:
答案 0 :(得分:1)
让我们按顺序完成这些。
获取特定Recipe
的成分时,如果您已有参考:每次都使用recipe.ingredients
。
获取具有特定值的特定Recipe
的成分(例如布尔标志值):最简单的可能是从上面的recipe.ingredients
开始,然后使用类似{{{ 1}} NSSet
来过滤它们。最优雅的是在objectsPassingTest
上设置一个fetched属性,只返回这些成分而不需要额外的代码(语法可能不会立即明显,有关详细信息,请参阅a previous answer I wrote)。这两个可能表现相同。最不吸引人的是获取请求。
获取出现在多个配方实例中的成分:可能是Recipe
实体的获取请求,其中谓词类似于Ingredient
,recipe in %@
被替换为%@
Recipe
个实例列表。
答案 1 :(得分:1)
一些基本信息:
*内存操作比磁盘操作快约100-1000倍
*获取请求执行始终是商店(磁盘)的行程,因此会降低性能。
在您的情况下,您需要查询一组“小”对象以获取信息
只需使用recipe.ingredients
集迭代它们就会逐个错误,每次访问都是商店之旅(故障解决)。
在这种情况下,请使用预取(在请求中,设置setRelationshipKeyPathsForPrefetching:
以预取ingredients
关系或执行获取具有相应谓词的集合的获取请求。)
如果您只需要特定数据,请使用获取请求方法仅检索您需要的数据。
如果您打算重复访问查询和信息的关系,只需使用预取来获取整个集合,然后在内存中查询。
我的观点是:
考虑最小化磁盘访问的方法(在任何情况下,您至少需要1次访问)。
如果您的数据太大而无法存储在内存中,或者要在内存中查询,请执行提取以仅获取所需的数据。
现在:
1.Consistency - 选择一种你觉得舒服并坚持使用的方法(我使用预取)
2.Readability - 使用属性比执行查询更具可读性,但是如果不使用预取则效率较低。
3.性能 - 磁盘访问会降低性能,但在某些情况下是不可避免的
4.Robustness - 获取请求表明您知道什么是最适合您的数据使用。明智地使用它。
要确保最大限度地减少磁盘访问,请启用SQLite调试
(-com.apple.CoreData.SQLDebug)
编辑:
答案 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];
正确的一般方法是什么?
获取请求是搜索给定实体的所有实例的好方法。您总是使用获取请求启动以获取一些对象。但是当你想要的对象以某种方式与你已经拥有的对象相关时,你可以(并且应该)使用这些关系来获得你想要的东西。