4

NSError オブジェクトへのポインターを引数として取るメソッドを使用して、NSInvocation オブジェクトを作成したいと考えています。この例は、メソッドです-

- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)mask error:(NSError **)errorPtr

このように呼び出しを設定することを理解しています

NSData *myData = [[NSData alloc] init];

SEL writeToFileSelector = @selector(writeToFile:options:error:);
NSMethodSignature *signature = [NSData instanceMethodSignatureForSelector:writeToFileSelector];

NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:myData];
[invocation setSelector:writeToFileSelector];

NSString *string = [NSString stringWithFormat:@"long cat"];
NSDataWritingOptions *dataOptions;
*dataOptions = NSDataWritingFileProtectionComplete;

[invocation setArgument:&string atIndex:2];
[invocation setArgument:&dataOptions atIndex:3];

writeToFile:Options:Error の場合: 最後の引数は、オブジェクトではなくポインターを受け取ることを想定しています。その結果、以下を実行しても機能しません -

NSError *err = nil;
[invocation setArgument:&err atIndex:4];

解決策がポインターへのポインターを作成することであることは論理的に思えますが、これによりコンパイラーの警告が発生します。それを適切に実行し、メモリ管理の問題を引き起こさないようにする方法がわかりません。

4

3 に答える 3

3

メソッドに渡す他の引数とまったく同じように引数を作成します。

ご指摘のとおり、メソッド シグネチャは最後の引数 (インデックス 4) に NSError ** を必要とします。そのため、宣言する必要がありますが、ちょっとした落とし穴があります。

NSError **errorPointer

NSError 変数を指す変数を提供します。しかし、変数を指すように指示していないため、nil を指します。したがって、呼び出しを起動すると、セレクターはエラーポインターが指す変数を変更できません。つまり、 を呼び出すようなもの[myData writeToFile:string options:dataOptions error:NULL]です。

したがって、NSError 変数も宣言し、そのアドレスを errorPointer が指す変数として割り当てる必要があります。

NSError *error;
NSError **errorPointer = &error;

これで、errorPointer を引数として渡すことができ、メソッドを呼び出したときに問題があったかどうかを後で調べることができます。もう少しヘルプが必要な場合は、NSInvocation に関するこの投稿を参照してください(ブログ投稿を指摘してくれたMark Dalrympleに感謝します)。

作成して呼び出しに渡す引数については、スコープを考慮する必要があることも認識することが重要です。私がここで尋ねた同様の質問を見てください。

于 2012-04-04T13:05:53.763 に答える
2

edelaney05 によって受け入れられた回答は素晴らしかったですが、ARC には少し調整が必要だと思います。(まだコメントを追加できないため、見つけたものを文書化するための新しい回答を作成しています)

そのまま、コンパイルエラーが発生しました:「明示的な所有権のない非const型 'NSError *'へのポインター」

これを調査したところ、次のものが必要であることがわかりました。

 NSError * __autoreleasing error = nil;
 NSError * __autoreleasing *errorPointer = &error;

この答えに私を導いた参照:

NSInvocation & NSError - __autorelease & メモリ クラッシャー

自動参照カウント: 明示的な所有権のない非 const 型 'NSError *' へのポインター

http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

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

于 2013-04-16T02:39:56.350 に答える
0

パラメータの型はで、エラーを書き込むNSError **an のアドレスを取得して取得します。NSError *に引数を設定するにはNSInvocation、引数の値のアドレスを に渡す必要があるため、変数 (ここではそれを呼び出します)setArgument:に入れ、そのアドレス (これは になります) を取得する必要があります。に渡します。後で変数は必要ありません。NSError **errPointerNSError ***setArgument:errPointer

NSError *err = nil;
NSError **errPointer = &err;
[invocation setArgument:&errPointer atIndex:4];
于 2012-05-11T18:53:17.583 に答える