4

学習 (実用的ではありませんが、まだ) の目的で、NSDictionary で次のメソッドを使用して、定義したテストを使用して値を持つキーのセットを返したいと思います。残念ながら、述語を指定する方法がわかりません。

NSDictionary keysOfEntriesPassingTest:
- (NSSet *)keysOfEntriesPassingTest:(BOOL (^)(id key, id obj, BOOL *stop))predicate

たとえば、私のすべての値が NSURL であり、ポート 8080 にあるすべての URL を取得したいとしましょう。これがコーディングの私の刺し傷です。正しい:

NSSet * mySet = [myDict keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) {
                 if( [[obj port] isEqual: [NSNumber numberWithInt: 8080]]) {
                     return key;
                 }]

これは、次のコンパイラ エラーが返されるためです。

'void (^)(struct objc_object *, struct objc_object *, BOOL *)' を初期化する互換性のないブロック ポインター型、予期される 'BOOL (^)(struct objc_object *, struct objc_object *, BOOL *)'

私は何が欠けていますか?述語が想定されて いる「ブロックオブジェクト」について詳しく説明しているドキュメントへのポインタをいただければ幸いです。
ありがとう!


そして、これは機能するコードです:

NSSet *mySet = [myDict keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop)
{
  if ([[obj port] isEqual:[NSNumber numberWithInt: 8080]])
     return YES;
   else
     return NO;
}];
4

2 に答える 2

7

バリーの答えを少し拡張します....

ブロックは、重要な違いが 1 つだけある関数ポインターのようなものです。ブロックは、含まれている return ステートメントから戻り値の型を推測する、あなたが言ったようなエラー メッセージを表示します (LLVM コンパイラのエラーはもう少し合理的なはずです)。

あなたが書いたとき:

NSSet * mySet = [myDict keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) {
                 if( [[obj port] isEqual: [NSNumber numberWithInt: 8080]]) {
                     return key;
                 }]

それを関数として考えてください:

BOOL bob(id key, id obj) {
    if( [[obj port] isEqual: [NSNumber numberWithInt: 8080]]) {
        return key;
    }
}

問題が見えますか?値を返さないコード パスがあるため、コンパイラは文句を言います。

于 2010-06-14T04:40:56.323 に答える
3

このエラーは、ブロックがBOOLではなくを返さなければならないことを示していますid。ドキュメントを確認してください。YESキー/オブジェクトのペアが目的のテストに合格した場合、戻ってくることが期待されていると思います。

于 2010-06-13T23:15:16.033 に答える