将SKNode对象用于NSDictionary中的键?(比较问题)



Objective-C

考虑这个代码:

SKNode *n1 = [SKNode new];
SKNode *n2 = [SKNode new];
NSMutableDictionary *d = [NSMutableDictionary new];
[d setObject:@"A" forKey:n1];
[d setObject:@"B" forKey:n2];

if ([d objectForKey:n1]) {
    NSLog(@"true");
}

我使用SKNode作为NSDictionary中的密钥。我需要测试给定的SKNode是否作为密钥存在。常见的测试方法似乎不起作用,因为上面的结果不会返回(或打印)"true"。以下代码也不会:

if ([d allKeys] containsObject:n1]) {
    NSLog(@"true");
}

如果我把钥匙串起来;即打印@"key1"、@"key2"、"true"。

有可能用这种方式进行测试吗?

(我突然想到,我写的评论实际上就是这个问题的答案。)

NSDictionary复制其密钥(使用NSCopying协议中的-copy)。SKNode符合NSCopy,但复制节点会返回一个与旧节点不同的新节点:

SKNode *a = [SKNode new];
SKNode *b = [a copy];
[a isEqual:b];  // NO
let a = SKNode()
let b = a.copy() as! SKNode
a == b  // false

因此,在字典中使用SKNodes作为关键字是不安全的。至于解决方法:也许可以使用节点的name作为密钥(如果节点的名称是唯一的)。您也可以使用NSMapTable,它不复制其密钥。

您的代码应该可以工作。所以这里有问题,可能是SKNode的hashcode和isEqual方法的实现。

记录两个键的哈希代码,检查什么是Equal:return,记录字典和所有键,并检查是否有任何意外情况。

PS。事实证明,jtbandes的答案是正确的。当然,按照我的建议,并记录下你会发现的一切,allKeys中的密钥并不是预期的,很有可能找到答案。

因此,如果你有一个类,它包含琐碎的hashcode和isEqual,只需将指针作为hashcode并比较isEqual的指针,那么要么有一个复制创建新对象而字典不起作用的类,要么有一个副本只返回原始对象而工作正常的类。

最新更新