2

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

给定 a recipe,访问其成分的正确方法是什么?

在这个例子中,使用 似乎很自然recipe.ingredients,但我同样可以使用NSFetchRequestforIngredient实体和 anNSPredicate来匹配配方。

现在假设我只想要“收集”的成分。这对我来说不太清楚 - 我是否应该使用一个获取请求来获取具有受配方和收集状态限制的谓词的成分?或者循环通过recipe.ingredients?

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

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

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

3 回答 3

1

让我们按顺序浏览这些。

  1. Recipe当您已经有参考资料时,获取特定的成分:recipe.ingredients每次都使用。

  2. 获取Recipe具有特定值的特定成分(例如布尔标志值):最简单的方法可能是从recipe.ingredients上面开始,然后使用NSSet's之类的东西objectsPassingTest来过滤它们。最优雅的是设置一个 fetched 属性Recipe,它只返回这些成分而没有额外的代码(语法可能不会立即显而易见,有关详细信息,请参阅我之前写的答案)。这两者的表现可能差不多。最不吸引人的是获取请求。

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

于 2013-05-08T20:38:06.037 回答
1

一些基本信息:

*内存操作比磁盘操作快约 100-1000 倍。
*获取请求的执行始终是对存储(磁盘)的一次访问,因此会降低性能。

在您的情况下,您有一组需要查询信息的“小”对象。简单地使用集合
对它们进行迭代就会一个一个地对它们进行故障排除,每次访问都将是一次商店之旅(故障解决)。recipe.ingredients

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

如果您只需要特定数据,则使用 fetch request 方法仅检索您需要的数据。

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

我的观点是:

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

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

为确保最小化磁盘访问,请打开 SQLite 调试
(-com.apple.CoreData.SQLDebug)

编辑:

错误行为

于 2013-05-08T20:55:53.530 回答
0

在这个例子中,使用 recipe.ingredients 似乎很自然,但我同样可以使用 NSFetchRequest 来使用带有 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];

什么是正确的一般方法?

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

于 2013-05-08T21:43:28.710 回答