7

ダブルポインターを引数として取るブロックを作成/使用することは可能ですか (そうであれば安全です)?

例えば:

- (void)methodWithBlock:(void (^)(NSError **error))block;


追加のコンテキスト、調査、および質問:

  • ARCを使用しています。
  • 上記のメソッドを宣言して呼び出そうとすると、XCode はメソッド呼び出しを次のようにオートコンプリートし[self methodWithBlock:^(NSError *__autoreleasing *error) {}]; ます__autoreleasing。ARCと関係があると思います。
  • これ可能で安全な場合、ポインタは他の場所と同じようにブロック内で逆参照できますか?
  • - (void)methodWithDoublePointer:(NSError **)error;一般に、私が説明していることを実行することと、単純にダブル ポインターをメソッド パラメーターとして渡すこと (例: )との重要な違いは何ですか? もしあれば、どのような特別な考慮事項を考慮に入れる必要がありますか(これも可能であると仮定して)?
4

3 に答える 3

4

はい、ポインターは常に単なるポインターです。メッセージを送信する前に、それを逆参照することを確認するだけで済みます (objc オブジェクトを想定)。

また、ポインターが nil の場合があることに注意してください。逆参照を試みる前に、常にチェックしてください。

@verec が言及したように、ARC を使用している場合は、パラメーターを __autoreleases として宣言する必要があります。

ドキュメントによると

__autoreleasing は、参照 (id *) によって渡され、戻り時に自動解放される引数を示すために使用されます。

id はオブジェクトへのポインタであることを覚えておいてください。

ポインターをメソッドまたはブロックへのポインターに渡すことに違いはありません。

于 2013-10-21T21:26:21.703 に答える
2

答えは、イエスとノーの両方...

基本レベルでは、ポインターをブロックへのポインターに渡すことは、それらをメソッドに渡すことと同じです。そして、ポインターが有効でなければならないという通常の条件で、完全に問題ありません。

ただし、これはここで__autoreleasing非常に重要であり、ARC およびpass-by-writebackと結びついています。ブロックの使用が期待どおりに機能するかどうかは、コンテキストに依存します。コンパイラはNSError * __autoreleasing *、ライトバックによるパスの実装の一部として型のパラメーターを渡すときに隠し変数を使用することが多いためです。

ライトバックによる受け渡しが必要でない場合、または不適切な場合は、ブロックがNSError * __strong *. 内部で何が起こっているかを説明するこの回答を読んでください。これは、コンテキストでブロック宣言が適切かどうかを判断するのに役立ちます。

要約すると、(a) ブロックを宣言することは問題ありませんが、(b) ブロックがどのように呼び出されるかを理解する必要があり、署名を変更する必要がある場合があります。

于 2013-10-22T02:32:46.780 に答える
0

警告: 未テスト

議論のために、次から始めましょう。

typedef NSError * NSErrorPtr ;

- (void) foo: (NSErrorPtr *) errPtr {
    *errorPtr = [NSError new] ;
}

errPtr は __weak も __strong も宣言されていません。

したがって、ARC によれば、そのコンテンツはfooリリースの責任の範囲内で割り当てられますが、どこかに常駐する必要があります。

どこ?

これは double ポインター自体のプロパティではないことに注意してください。しかし、割り当てのパターンについて。

検討:

int ** arrayOfarrayOfInts = {
    {1, 2, 3, 4}    
,   {5, 6, 7, 8}
} ;

- (void) incrementElement: (int **) elem {
    ++(**elem) ;
}

- (void) bumpFirstColByOne {
    for (int i = 0 ; i < 2 ; ++ i) {
       int * arrayOfInt = arrayOfarrayOfInts[i] ;
       int ** second = &arrayOfInt[0] ;
       [self incrementElement: second] ;
    }
}

割り当てが行われていないため、ここでは __autorelease は必要ありません ...

于 2013-10-21T21:51:02.653 に答える