4

NSErrorオブジェクトへのポインタを引数として取るメソッドを使用してNSInvocationオブジェクトを作成したいとします。この例は方法だろう - 私はWRITETOFILEについては、このオブジェクトへのポインタを引数として取るメソッドを使用してNSInvocationオブジェクトを作成する方法

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]; 

ように私の呼び出しを設定することをundersand

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

:オプション:エラー:最後の引数はポインタを受け取ることを期待していますオブジェクトの代わりに。

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

それは解決策は、ポインタへのポインタを作成するかもしれないと論理的なようだが、これはコンパイラの警告が発生する - 動作しない次の操作を実行した結果。私はそれを正しく実行し、メモリ管理の問題を作成しない方法がわかりません。

答えて

3

あなたは、メソッドに渡す他の引数と同じものを作成します。

あなたが指摘したように、メソッドシグネチャは、最後の引数(インデックス4)にNSError **を必要とします。だから、あなたは1つを宣言する必要がありますが、ちょっとした問題があります。

NSError **errorPointer

あなたにNSError変数を指す変数を与えます。しかし、変数を指すように指示していないので、nilを指しています。したがって、呼び出しを起動すると、セレクタはエラーポインタが指し示す変数を変更することができません。言い換えれば、それは[myData writeToFile:string options:dataOptions error:NULL]と呼ぶようになります。

だから、あなたもNSError変数を宣言して、あなたのerrorPointerが指すべきで変数としてそのアドレスを割り当てることをお勧めします:今、あなたは、引数としてerrorPointerに渡すことができます

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

、そしてあなたメソッドを呼び出したときに問題があった場合は、後でそれを調べることができます。 をもう一度調べてください(ブログ投稿を指摘するために、Mark Dalrympleへの帽子の先端)

あなたが作成してあなたの呼び出しに渡す引数の範囲を考慮する必要があることを理解することも重要です。私が尋ねた同様の質問を見てくださいhere

+2

"しかし、変数を指すように指示していないので、nilを指しています。"何?いいえ、定義されていません – user102008

+0

"errorPointerを引数として渡すことができるようになりました。"これを渡す方法は説明していません。 – user102008

+2

#1 ARCでは、未割り当てのローカルポインタ変数は自動的にnilに設定されます。 Cまたは非ARC Obj-Cでは正しいです。 #2 errorPointerを第4引数 '[invocation setArgument:&errorPointer atIndex:4]'に渡すには – edelaney05

0

パラメータタイプはNSError **です。これは、エラーを書き留めたいアドレスNSError *から取得します。 NSInvocationに引数を設定するには、引数の値のアドレスをsetArgument:に渡す必要がありますので、NSError **を変数に設定する必要があります(私はerrPointerと呼んでいます)。 NSError ***)はsetArgument:に渡されます。その後、errPointer変数は必要ありません。

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

edelaney05の回答が良かったのですが、ARCの調整が少し必要だと思います。明示的な所有権を 「ポインタ非const型 『NSError *』へ: の通りです

を(私は、私が見つけたもの文書化するために、新しい答えを作成し、まだコメントを追加することはできません)、私はコンパイルエラーを得ました「

は、私はこれを調査し、私は必要なことがわかった。この答えに私を導いた

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

参考文献:

NSInvocation & NSError - __autoreleasing & memory crasher

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

Automatic Reference Counting: Pointer to non-const type 'NSError *' with no explicit ownership

"は__autoreleasingは参照によって渡され(ID *)とリターン時に自動解放された引数を表すために使用されます。"

関連する問題