Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/99.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c NSSet-检查NSValue相等性的成员_Objective C_Ios_Ipad_Equality_Nsset - Fatal编程技术网

Objective c NSSet-检查NSValue相等性的成员

Objective c NSSet-检查NSValue相等性的成员,objective-c,ios,ipad,equality,nsset,Objective C,Ios,Ipad,Equality,Nsset,我有一个NSSet包含数千个NSValue对象(包装CGPoints)。我想很快找到CGPoint值是否存在于NSSet中。在我看来,NSSet的成员:方法可能在这里起作用,只是它使用isEqual:检查相等性NSValue对象使用isEqualToValue:,因此当我执行代码时: [mySet member:valueToCheck]; 它实际上会导致Xcode崩溃 1) 对于NSValue对象,是否有某种方法可以使用自定义相等性检查来执行此操作 2) 这是否是最好的方法(即成员:首先足够

我有一个
NSSet
包含数千个
NSValue
对象(包装
CGPoints
)。我想很快找到
CGPoint
值是否存在于
NSSet
中。在我看来,
NSSet
成员:
方法可能在这里起作用,只是它使用
isEqual:
检查相等性
NSValue
对象使用
isEqualToValue:
,因此当我执行代码时:

[mySet member:valueToCheck];
它实际上会导致Xcode崩溃

1) 对于
NSValue
对象,是否有某种方法可以使用自定义相等性检查来执行此操作

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


多亏了一个解决方案是将
NSSet
子类化,并覆盖
成员:
,以进行您自己的比较。然后,您自己的比较可以简单地调用
isEqualToValue:
。请查看中的子类化注释

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

回答第2个问题:

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

为每个像素存储巨大的二维阵列可能是最快的方法,但它会在内存消耗方面扼杀你。你需要一些快速但又轻便的东西

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

例如,一个非常简单的方法是实现一个四叉树,首先将屏幕(或区域)分成4个相等的部分。然后,如果需要,在需要的地方,将特定的单元格也分成4部分。这样做,直到每个单元包含足够小的点数,这样就可以对所有单元进行暴力测试。 您可以在wiki上找到非常好的描述:


希望这能有所帮助,

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

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"
NSLog(@"%d", ([v1 hash] == [v2 hash])); //logs "1"
-哈希
不是问题:

NSValue *v1 = [NSValue valueWithPoint:NSMakePoint(1, 1)];
NSValue *v2 = [NSValue valueWithPoint:NSMakePoint(1, 1)];
NSLog(@"%d", [v1 isEqual:v2]); //logs "1"
NSLog(@"%d", ([v1 hash] == [v2 hash])); //logs "1"
它们是不同的对象:

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

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

这不仅仅是
-isEqual:
的问题,您可能还存在该方法的问题。如果要使用NSSet,可能应该创建一个封装CGPoint的自定义类
-isEqual:
是微不足道的,
-hash
可以通过组合两个坐标的位并将其视为整数的某种方法来实现


您还需要实现
NSCopying
协议,如果您的点是不可变的(只需在
-copyWithZone:
中保留并返回self),该协议也很简单

[mySet成员:valueToCheck]
不应崩溃。NSValue的
isEqual:
在这里尝试时效果很好,事实上,当给定另一个NSValue进行比较时,可能会调用
isEqualToValue:
valueToCheck
真的是NSValue,还是CGPoint

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

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

这些函数的约束可能与NSObject的
hash
isEqual:
方法相同,任何相等的函数都必须具有相同的hash。描述了
customEqualFunction
customHashFunction
的C风格原型,并且。

否。不要将
NSSet
子类化。这是一个类集群,对它进行子类化是一项非常重要的任务。@Dave DeLong:子类化
NSSet
很好。我同意这通常是不必要的,但也可以这样做。文档中没有说明它是一个类集群。下面是从 NSSET 文档中提取的:“子类注释应该不需要子类化。如果需要自定义行为,最好考虑组合而不是子类。方法要在子类中重写,必须重写它的所有原始方法:计数成员:ObjuttEnMurror”。它是一个类集群。文档中说,它可以免费桥接到
CFSet
,而免费桥接只在类群集的情况下起作用。@Dave说得很对。你的答案更值得考虑。(我目前只有web访问权限,因此无法测试我提出的解决方案。)文档中没有提到它是一个类集群,这有点奇怪。NSArray文档非常清楚。另外,我面前有消息来源;)您可以通过实例化一个
NSSet
并找出实例的
类的名称来验证这一点。这是一个
NSCFSet
NSCF*
是该类为TFB的指示器)。这是一个非常有用的答案,谢谢。如果我使用