NSArray containsObject不像宣传的那样工作

时间:2013-10-24 19:59:51

标签: objective-c cocoa nsarray

因此,Apple的文档说明了containsObject

  

此方法确定aObject是否存在于数组中   向每个数组的对象发送一个isEqual:消息(和   将anObject作为参数传递给每个isEqual:message)。

您可以找到这些文档here

然而,我正在经历几乎完全相反的效果。我没有向我的数组中的每个对象发送isEqual:,而是为数组中的每个对象发送isEqual:消息。

例如,我有两个类:FlxSortFlxFieldKeyFlxSort类包含一个字段键,如果它传递的isEqual:对象与它所拥有的键匹配,我会覆盖FlxFieldKey以返回true。理论上,这应该允许我检查数组中是否存在具有特定键的FlxSort对象。但是,FlxFieldKey不是(并且不应该)知道FlxSort对象,因此如果在FlxSort isEqual中提供currentSorts对象,它将始终返回false信息。因此,在下面的代码中,我希望isEqual:中的每个对象都会为_avialableKeys中的每个密钥发送_availableKeys消息。相反,isEqual:中的每个密钥都会发送NSMutableArray *keys = [NSMutableArray arrayWithCapacity:_avialableKeys.count]; NSArray *currentSorts = _sortGroup.sorts; for (FlxFieldKey *key in _avialableKeys){ if (![currentSorts containsObject:key]){ [keys addObject:key]; } } 消息。我已经使用日志记录和断点检查了这两个。

[NSArray containsObject:]

我在这里错过了什么吗?

更新
即使我在询问containsObject,我也得到了很多关于我实现非对称平等的反馈。所以我想澄清一下,我的实施是出于好奇而产生的实验。原始代码根本没有使用NSMutableArray *keys = [NSMutableArray arrayWithCapacity:_avialableKeys.count]; NSArray *currentSorts = _sortGroup.sorts; for (FlxFieldKey *key in _avialableKeys){ BOOL found = NO; for (FlxSort *sort in currentSorts){ if ([sort.key isEqual:key]){ found = YES; break; } } if (!found){ [keys addObject:key]; } }

containsObject

我很好奇我是否可以装isEqual:在上述情况下工作。当然,正如一些人所指出的那样,创建不对称平等是一个坏主意,并直接反对Apple的建议。我可以更改FlxFieldKey中的FlxSort方法以考虑hash个对象,这将恢复两个类之间的对称相等...等等。你仍然可以得到A == B,A == C,但是B!= C.而且仍然存在{{1}}问题(它​​们需要相同)。

让我重申一下:你不想这样做(非对称平等)。至少,不在生产代码中。我只是在这里看到我 可以 做什么,而不是我 应该 做什么。我承认,在原始问题中不澄清这一点是不负责任的,因为经验不足的开发人员可能会认为这种实现是可行的。我为此道歉。

是的,一旦我能鼓起勇气再次进入Apple的bug记者,我可能会在Radar报告一个文档错误......

2 个答案:

答案 0 :(得分:1)

我不知道这是实际发生的事情,但实施containsObject:为(松散地):

for( id containedObj in self ){
    if( [testObj isEqual:containedObj] ){
        return YES;
    }
}

表示testObj的{​​{1}}实现可以直接缓存和调用,而不是每次都通过isEqual:调度的消息。因为objc_msgSend() s可能是异质的,所以如果比较是相反的,那么就不可能缓存每个调用,就像文档所说的那样。

那里有一个微小的性能提升,可以为大型阵列辩护。

你应该提交一个doc bug,尽管正如Rob Napier指出的那样,如果你让平等不对称,这只是一个问题,这本身就是一个有问题的想法。

答案 1 :(得分:0)

你是对的,这是实施和文档之间的差异,你应该file a bug on radar

然而,它的目的是在您的实现中突出显示设计问题。

比较的顺序真的不应该是平等

[objectA isEqual:objectB] == [objectB isEqual:objectA];

应该永远是真的,除非你故意想遇到麻烦。

那就是说我相信NSSet更适合于那种任务,因为containsObject:操作在恒定时间内执行,而NSArray操作则是hash。 }。在这种情况下,您还需要覆盖{{1}}方法。