2

メソッドを動的に呼び出すには、NSInvocation を使用する必要があります。ここで私が試したこと:

NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[messageRecord.senderController class] instanceMethodSignatureForSelector:messageRecord.receiverAction]];

[invocation setSelector:messageRecord.receiverAction];
[invocation setTarget: messageRecord.senderController];
[invocation setArgument: &(message.data) atIndex:2];
[invocation invoke];

messageRecord.senderControllerはメソッドが呼び出されるオブジェクトであり、messageRecord.receiverActionこのコードに指定されたセレクターであることに言及する必要があります。また、message.dataタイプ (NSArray *) のオブジェクトであり、適切に初期化されています。

このコードでは、次のコンパイル時エラーが発生します

Address of property expression requested

呼び出しプロセスを次のように変更すると、期待どおりに動作します。

NSArray *dataArray = message.data;

[invocation setSelector:messageRecord.receiverAction];
[invocation setTarget: messageRecord.senderController];
[invocation setArgument: &dataArray atIndex:2];
[invocation invoke];

2 つの唯一の違いは、ローカル NSArray ポインターを作成し、それに message.data を割り当てたことです。message.data後で、それ自体ではなく、新しく作成されたポインターのアドレスを指定しました。

なぜそれが機能したのですか?とにかく違いは何ですか?

4

2 に答える 2

2

Shimanski Ahem が述べたように、プロパティはアドレスを持つものではありません。プロパティは、getter メソッドと setter メソッドのペアです。それでおしまい。getter メソッドと setter メソッドは、ユーザーが提供するか、インスタンス変数に基づいてコンパイラによって合成されます。それらがあなたによって提供された場合、それらはいくつかのインスタンス変数に基づくこともできますが、追加のロジックを実行します。または、他のものに基づいて完全に動的に値を生成することもできます。したがって、プロパティに対応する「インスタンス変数」がどこかにない可能性があります。

ゲッターとセッターが合成され、それらが基づいているインスタンス変数がわかっている場合 (これは合成宣言から取得できます。合成で明示的に指定されていない場合はプロパティ名と同じです。または、_data(コンパイラの最近のバージョンで合成が省略され、暗黙的に指定されている場合、Shimanski Artem はこのように表示します。

しかし、少し戻って、そもそもなぜ値へのポインターが必要なのかを尋ねてください。目的は何ですか?元の値へのポインターを使用した場合、またはその値のコピーへのポインターを使用した場合、違いはありますか? メソッドがどのようにsetArgument:動作し、なぜポインターが必要なのかを理解することは、これらの質問の多くに答えるのに役立ちます。呼び出しの引数の 1 つに任意の値を設定できるため、実際にはvaluesetArgument:を気にします。では、なぜ値を直接渡さないのでしょうか? さて、どんなタイプでしょう?Cでは型が異なればサイズも異なるため、それは不可能です。代わりに、値へのポインターを指定するように要求し (これはどの型でも機能します)、そこからコピーします。したがって、値のみを気にします特定のアドレスではありません。これが、(あなたが観察したように)setArgument:アドレス指定できないもの(プロパティ、より複雑な式、またはthisObjective-C ++など)で使用したい場合、単純に一時変数に割り当ててそのアドレスを取得します。

于 2012-11-28T21:57:31.970 に答える
0

物件の住所を取得することはできません。言語仕様です。このフォームを試すことができます:

[invocation setArgument: &(message->data) atIndex:2];
于 2012-11-28T10:02:35.777 に答える