NSSet -member检查NSValue的相等性

我有一个包含数千个NSValue对象的NSSet (包装CGPoints )。 我想很快找到NSSet是否存在给定的CGPoint值。 在我看来, NSSetmember:方法可以在这里完成工作,除了它使用isEqual:检查相等性。 NSValue对象使用isEqualToValue: ,因此当我执行代码时:

 [mySet member:valueToCheck]; 

它实际上导致Xcode崩溃。

1)是否有某种方法可以使用自定义相等性检查来使其适用于NSValue对象?

2)这是否是最好的方法(即member:首先是否足够快)? 场景是我有一个NSSet包含大量代表屏幕(iPad)像素的点。 后来我需要以每秒数千点的速度轰击那一组,看看它们是否存在于集合中。 我的方法似乎很难实现这一点。 我想创建类似于一个巨大的二维位数组的东西,每个索引代表一个屏幕上的像素。 一旦我知道了我正在测试的那一点,我就可以直接跳到arrays中的那一点并检查1或0 ……这听起来好不好?

谢谢

你能把它变成一个简单的可重复的案例吗? 例如,我刚试过:

 NSValue *v = [NSValue valueWithCGPoint:CGPointMake(1, 1)]; NSSet *s = [NSSet setWithObject:v]; NSLog(@"%@", [s member:[NSValue valueWithCGPoint:CGPointMake(1, 1)]]); 

但它的工作正常。

编辑

-isEqual:不是问题:

 NSValue *v1 = [NSValue valueWithPoint:NSMakePoint(1, 1)]; NSValue *v2 = [NSValue valueWithPoint:NSMakePoint(1, 1)]; NSLog(@"%d", [v1 isEqual:v2]); //logs "1" 

-hash不是问题:

 NSLog(@"%d", ([v1 hash] == [v2 hash])); //logs "1" 

它们是不同的对象:

 NSLog(@"%d", (v1 != v2)); //logs "1" 

问题出在您的代码中。 尝试清洁和重建。

回答否。 2:

我不知道NSSet是如何在内部实现的,但考虑到你知道你在存储点(使用X和Y),我认为通过实现自己的分区算法会更好。 我个人会选择我自己的实现而不是NSSet,如果你说你有数千点。

为每个像素存储巨大的二维数组可能是最快的方法,但它会在内存消耗方面杀死你。 你需要快速的东西,但也要轻巧。

有很多算法,您可以通过在维基百科或谷歌上搜索“空间分区算法”找到它们。 这还取决于您的编程技巧,以及您愿意投入多少时间。

例如,一个非常简单的方法是实现四叉树,在这里您可以将屏幕(或区域)分成4个相等的部分。 然后,如果需要,可以将该特定单元划分为4个部分。 并且这样做直到每个单元格包含足够少的点数,以便您可以对所有单元格进行暴力测试。 你可以在wiki上找到一个非常好的描述: http : //en.wikipedia.org/wiki/Quadtree

希望这可以帮助,

[mySet member:valueToCheck]不应该崩溃。 NSValue的isEqual:当我在这里尝试时工作正常,实际上可能调用isEqualToValue:当给出另一个NSValue进行比较时。 valueToCheck真的是NSValue,还是CGPoint?

无法覆盖NSSet的默认哈希和比较方法。 但是NSSet与CFSetRef是免费的桥接,您可以在那里轻松指定自定义哈希和比较方法:

 CFSetCallBacks callbacks = kCFTypeSetCallBacks; callbacks.equal = customEqualFunction; callbacks.hash = customHashFunction; NSMutableSet *set = (NSMutableSet *)CFSetCreateMutable(NULL, 0, &callbacks); 

对这些函数的约束大概与NSObject的hashisEqual:方法相同,任何相同的东西必须具有相同的散列。 这里和这里描述了customEqualFunctioncustomHashFunction的C风格原型。

一种解决方案是子类化NSSet并覆盖member:进行自己的比较。 然后你自己的比较可以简单地调用isEqualToValue: . 查看NSSet文档中的子类注释。

另一种方法是向实现isEqual: NSValue添加一个类别isEqual: 。 在这种情况下,我更喜欢子类化,因为它是一个更有限的解决方案。

这不仅仅是-isEqual:一个问题-isEqual:你也可能遇到-hash方法的问题。 如果要使用NSSet,则应该创建一个包装CGPoint的自定义类。 -isEqual:然后是微不足道的, -hash可以通过组合两个坐标的位然后将它们作为NSUInteger处理的某种方法来实现。

您还需要实现NSCopying协议,如果您的点是不可变的,那么这也是微不足道的(只需保留并返回self in -copyWithZone: