2011-03-18 95 views
5

我需要确定对象是否包括在核心数据一对多的关系(这是一个NSSet中),我试图决定哪两种解决方案更好:1哪个更好,NSSet的containsObject或者快速枚举?

解决方案)

if ([managedObject.items containsObject:itemOfInterest]) 
    return … 

方案二)

for (NSManagedObject *item in managedObject.items) 
    if ([item == itemOfInterest]) 
     return … 

解决方案1更简洁,但NSSet中类文献说,快速列举的性能比的NSSet的objectEnumerator更好。它是否也比containsObject执行得更好?

+0

我可能在这里错过了一些东西,但为什么你需要搜索呢?如果你已经有一个关系的每一边有两个对象,你已经有了你需要的信息。这是一种多对多的关系,还是一对多而没有互惠关系? – TechZen 2011-03-19 21:15:39

+0

@ TechZen:根据用户的搜索条件进行提取。结果显示在表格中。用户通过表格对这些结果进行选择。还有另一张带有多对多关系成员的表格,并带有复选框。复选框状态必须根据是否全部,无或所选对象包含其项目来设置。可能涉及很多对象,因此使用最有效的方法很重要。感谢Raybould先生和Napier先生的建议,我确信containsObject是最佳选择。 – Wienke 2011-03-19 23:01:00

回答

5

我总是去选择1

它更简洁,我可以告诉正是你想要的代码做,机会是containsObject包含了一些非常漂亮的优化。

20

也没有。您应该使用带谓词的NSFetchRequest。你的模式可能会意外地错误的关系,这是非常昂贵的,不需要检查它是否包含一个对象。有些方法需要小心,而不是错误的整个关系,但它很脆弱(搜索的小改变会导致性能的巨大变化),所以最好养成使用NSFetchRequest而不是搜索集合的习惯。我喜欢在这些情况下将我的fetchLimit设置为1,所以一旦找到它,它就停止查找。

为方便起见,您可能需要在托管对象上创建-containsFoo:方法,以便您不必在整个位置编写提取逻辑。

上述两个解决方案略有不同。第一个测试集合中是否有对象isEqual:itemOfInterest。您的第二个解决方案测试集合中是否有与itemOfInterest相同的内存位置中的对象。对于具有自定义isEqual:逻辑的对象,这些可以返回不同的结果。这意味着对于非核心数据收集,解决方案2的速度可能会稍微快一些,但这是因为您实际上正在测试不同的东西,而不是因为对象枚举。 (实际上,这只适用于小型收藏;请参阅下文。)

为什么您认为解决方案1使用-objectEnumerator

正如@James Raybould指出的那样,出于性能原因,您通常不应该尝试重写内置方法。如果解决方案2的isEqual:版本比解决方案1更快,您是否认为Apple会使用解决方案2中的代码实施-containsObject:

实际上,底层CFSet是作为散列实现的,所以检查遏制是对数而不是线性。一般而言,对于具有合理散列函数的大集合,解决方案1将更快。请参阅CFSet.c中的代码。寻找CFSetContainsValue()。当然,不能保证CFSet的实现保持不变,但对于理解Cocoa中通常如何处理性能问题非常有用。

+1

忽略我的评论 - 这是我读过的最好答案之一! – 2011-03-18 20:31:16

+0

感谢您的深入响应。我从中学到了很多东西。 有问题的搜索是在表中选择的托管对象上执行的,其中的内容本身是特定获取请求的结果。所以我确实需要使用缓存对象,而不是运行另一个获取。 (我用“predicateWithFormat:@”ANY items ==%@“,itemSelected”时使用了一个抓取,当基于这个对多关系从商店中拉出物体时)。 – Wienke 2011-03-18 20:52:03

+0

你的情况听起来很合理,'containsObject:'这是你最好的选择,正如詹姆斯指出的那样:你是正确的,你不应该再次获取*,并且'containsObject:'使用'hash'和'isEqual:'这些被记录为非错误的(你不应该重写这些方法对于'NSManagedObject')。 – 2011-03-19 01:02:48