2012-03-30 6 views
2

私はすべてのタイプの引数を持つ任意のセレクタを取り、RPCコールをワイヤに送信するキャッチオールプロキシを作成しようとしています。この場合、メソッドのシグネチャはエンドユーザが任意に作成できるため、知られていません。methodSignatureForSelector: "catch-all"メソッドの署名を作成できますか?

メソッドのシグネチャでは、各引数に型エンコードを指定する必要があります。絶対に何か(ポインタ、int、他のすべて)を意味する型エンコーディングはありますか?さもなければ、この効果を達成する別の方法がありますか?

答えて

2

"並べ替え"ですが、実際にはそうではありません。または、少なくとも、実質的にはそうではありません。

NSInvocationで認識できないメソッド呼び出しがラップアップされ、NSInvocationが破損するようなメソッド転送プロトコルを実装できますが、実際には多くの理由で実用的ではありません。

まず、比較的単純な引数型の場合にのみ実際に動作します。 C ABIは、複雑な引数(構造体、C++オブジェクトなど)がうまくいく方法でスタックにエンコードされるようなものです。実際、フレームをデコードするのに十分なメタデータがない場合には、それらをエンコードすることができます。

第二に、「セレクタは、ユーザが任意に作成することができる」システムの任意の種類はそれについて非常に明確な臭いを有します。 「あなたはそれを難し​​い方法でやっている」という匂い。 Objective-Cは、例外的に動的ではあるが、実際にこのレベルの純粋なメタオブジェクトパターンをサポートするようには設計されていませんでした。

同様に、そのような結果として生じるシステムは、例外的に脆弱になります。 「任意のセレクタ」が例えば@selector(ハッシュ)である場合はどうでしょうか?

2

このキャッチオールプロキシとそれを転送する必要があることについて詳しく説明できますか?プロキシが唯一つのターゲットにそれぞれメッセージを転送する必要がある場合

、それは実行時にその-forwardingTargetForSelector:で行うことができます。そうでない場合(たとえば、複数のターゲットに転送する必要がある、または他の複雑な操作を行う必要がある場合)、それを処理するには-forwardInvocation:を実装する必要があります。 -forwardInvocation:を使用して呼び出しを処理するには、呼び出しを作成できるようにメソッドの署名を取得する必要があるため、-messageSignatureForSelector:を実装する必要があります。 (それを別のオブジェクトに転送しても、そのオブジェクトは直接メソッドを実装するか、+resolveInstanceMethod:に対応するメソッドを追加するか、-forwardInvocation:を使用して処理します)。

メソッドシグネチャは、引数の型と戻り値の型をエンコードします。この情報が呼び出しに必要な理由は、これらの引数が渡されたときに、宣言の型に応じてコンパイル時に(たぶん連続して)メモリに配置されるということです。大きなstructパラメーターは、intパラメーターより多くのスペースを占有します。 doubleはおそらくintより大きいでしょう。呼び出しにはこれらの引数をすべて格納し、インデックスにアクセスまたは変更できるようにする必要があります。型(または少なくとも型のサイズ)を知っていない限り、実行時に引数がどのようにレイアウトされるか把握する方法はありません。

また、メッセージの受け渡しメカニズムは、他のメソッド(objc_msgSendを呼び出します)(一部のプラットフォームでは、doubleを返すメソッドはobjc_msgSend_fpretを使用します)から構造体(objc_msgSend_stretを呼び出します)を返すメソッドでも異なります。前者の場合、構造体は直接返されませんが、書き込む場所は余分なポインタ引数としてoutパラメータとして渡されます。したがって、戻り値の型が分かっていることは、呼び出しでの呼び出しと戻り値の処理にも重要です。

呼び出しを他のオブジェクトに転送しても、最終的にはそのオブジェクト(またはオブジェクトを行末に転送するオブジェクト)は何とかメソッドのシグネチャを知っている必要があります。だからあなたがそれを必要とするセレクタの署名のためにそのオブジェクトを尋ねてみませんか?

異なるタイプのサイズが異なるため、すべてのもので機能する「安全な」署名はありません。

関連する問題