4

私はNSSet何千ものNSValueオブジェクトを含んでいます(ラッピングCGPoints)。CGPoint指定された値がに存在するかどうかを非常に迅速に確認したいと思いますNSSet。を使用して等価性をチェックすることを除いて、ここでmember:は an のメソッドが機能するように思えます。オブジェクトは を使用するので、コードを実行すると:NSSetisEqual:NSValueisEqualToValue:

[mySet member:valueToCheck];

実際に Xcode がクラッシュします。

1) カスタム等値チェックを使用してNSValueオブジェクトに対してこれを機能させる方法はありますか?

2)これは最善のアプローチですか(つまりmember:、そもそも十分に速いですか)?シナリオはNSSet、画面 (iPad) 上のピクセルを表す多数のポイントを含むことです。後で、セットに存在するかどうかを確認するために、1 秒あたり何千ものポイントでそのセットを攻撃する必要があります。これを達成するための私のアプローチは大雑把に思えます。各インデックスが画面上のピクセルを表す巨大な 2 次元ビット配列のようなものを作成することを考えました。テスト対象のポイントがわかったら、配列内のそのポイントに直接ジャンプして、1 または 0 をチェックできます... これは良い音ですか、悪い音ですか?

ありがとう

4

5 に答える 5

10

これを単純な再現可能なケースにできますか? たとえば、私はちょうど試しました:

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"

問題はあなたのコードにあります。クリーニングして再構築してみてください。

于 2011-04-19T16:27:05.560 に答える
1

いいえと答えるには。2:

NSSet が内部でどのように実装されているかはわかりませんが、(X と Y を使用して) ポイントを格納していることを知っていることを考えると、独自のパーティショニング アルゴリズムを実装したほうがよいと思います。個人的には、何千ものポイントがあると言うなら、NSSet よりも独自の実装を選択します。

ピクセルごとに巨大な 2 次元配列を格納するのがおそらく最速の方法ですが、メモリ消費の点で致命的です。高速で軽量なものが必要です。

そこには多くのアルゴリズムがあり、ウィキペディアまたはグーグルで「空間分割アルゴリズム」を検索することでそれらを見つけることができます。また、プログラミングのスキルと、これにどれだけの時間を投資しても構わないと思っているかにもよります。

たとえば、非常に単純なものは、画面 (または領域) を 4 つの等しい部分に分割することから始める四分木を実装することです。次に、必要に応じて、その特定のセルを 4 つの部分に分割します。そして、各セルに含まれるポイントの数が十分に少なくなるまでこれを行い、すべてのポイントをブルート フォース テストできるようにします。ウィキで非常に優れた説明を見つけることができます: http://en.wikipedia.org/wiki/Quadtree

お役に立てれば、

于 2011-04-19T16:24:05.933 に答える
1

[mySet member:valueToCheck]クラッシュしてはいけません。ここで試してみると、 NSValueは正常に動作し、実際には、比較する別の NSValue が指定されたときにisEqual:おそらく呼び出されます。isEqualToValue:本当にvalueToCheckNSValue ですか、それとも CGPoint ですか?

NSSetのデフォルトのハッシュおよび比較メソッドをオーバーライドする方法はありません。しかし、NSSet は無料で にブリッジされておりCFSetRef、そこでカスタムのハッシュと比較方法を簡単に指定できます。

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

これらの関数の制約は、おそらく NSObjecthashおよびisEqual:メソッドの制約と同じであり、等しいものはすべて同じハッシュを持つ必要があります。との C スタイルのプロトタイプについては、こちらcustomEqualFunctionこちらでcustomHashFunction説明しています。

于 2011-04-19T16:36:02.013 に答える
-1

だけの問題ではなく、 -hashメソッド-isEqual:にも問題がある可能性があります。NSSet を使用する場合は、おそらく CGPoint をラップするカスタム クラスを作成する必要があります。 は自明であり、両方の座標のビットを組み合わせて NSUInteger として扱う何らかの方法で実装できます。 -isEqual:-hash

NSCopyingまた、ポイントが不変である場合にも簡単なプロトコルを実装する必要があります(保持して self を返すだけです-copyWithZone:)。

于 2011-04-19T16:30:39.660 に答える
-1

1 つの解決策は、サブクラスNSSet化してオーバーライドmember:し、独自の比較を行うことです。独自の比較では、単純に call を呼び出すことができますisEqualToValue:NSSetドキュメントのサブクラス化に関する注意事項を参照してください。

NSValue別のアプローチは、その implementsにカテゴリを追加することisEqual:です。この場合、より制約のあるソリューションであるため、サブクラス化をお勧めします。

于 2011-04-19T16:17:02.887 に答える