3

因此,Apple 的文档是这样说的containsObject

此方法通过向数组的每个对象发送 isEqual: 消息(并将 anObject 作为参数传递给每个 isEqual: 消息)来确定数组中是否存在 anObject。

您可以在此处找到这些文档。

但是,我正在经历几乎完全相反的效果。isEqual:我提供的对象不是发送给数组中的每个对象,而是发送数组isEqual:中每个对象的消息。

例如,我有两个类:FlxSortFlxFieldKey. 一个类包含一个字段键,如果它传递了一个与它所拥有的键匹配的对象,FlxSort我已经重写了isEqual:它返回 true 。FlxFieldKey理论上,这应该允许我检查FlxSort数组中是否存在具有特定键的对象。但是,FlxFieldKey它不(也不应该)知道该对象,因此如果在其消息中FlxSort提供了一个对象,它将始终返回 false 。所以在下面的代码中,我希望每个对象都被发送给每个键的消息。相反,每个输入的键都会发送消息。我已经通过日志记录和断点检查了这一点。FlxSortisEqualcurrentSortsisEqual:_avialableKeys_availableKeysisEqual:

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在上述情况下工作。当然,正如一些人所指出的,创建不对称平等是一个坏主意,并且直接违背了 Apple 的建议。我可以更改 中的isEqual:方法FlxFieldKey以考虑FlxSort对象,这将恢复两个类之间的对称相等性......有点。你仍然可以得到 A == B,A == C,但是 B != C。这仍然存在hash问题(它们必须相同)。

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

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

4

2 回答 2

1

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

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

意味着testObjisEqual:实现可以直接被缓存和调用,而不是objc_msgSend()每次都派发消息。因为NSArrays 可以是异构的,所以如果比较是相反的,就不可能缓存每个调用,就像文档所说的那样。

那里有轻微的性能提升,这可能证明自己适合大型阵列。

您可能应该提交一个文档错误,尽管正如 Rob Napier 指出的那样,如果您使相等不对称,这只是一个问题,这本身就是一个有问题的想法。

于 2013-10-24T21:02:25.457 回答
0

你是对的,这是实现和文档之间的差异,你应该在 radar 上提交一个错误

但是,它的目的是突出您的实现中的设计问题。

比较的顺序真的不应该像平等一样重要

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

应该总是正确的,除非你故意想遇到麻烦。

话虽这么说,我相信 aNSSet更适合这种任务,因为containsObject:操作在恒定时间内执行,而不是在NSArray. 在这种情况下,您还需要覆盖该hash方法。

于 2013-10-24T23:48:35.590 回答