2010-12-30 9 views
1

私はvery clever KVO patternのように、セレクタをコンテキストとして渡すことができるメソッドポインタに解決するようにしています。コンテキストとしてメソッドを持つDispatcherパターン

パターンの一部の最後の部分は、私にいくつかのトラブルを与えている:メソッドポインタが逆参照し、一見呼び出され

- (void)observeValueForKeyPath:(NSString *)keyPath 
    ofObject:(id)object 
    change:(NSDictionary *)change 
    context:(void *)context 
{ 
    Method m = (Method)context; 
    (void(*)(id,SEL,id,id,id))(m->method_imp)(owner, m->method_name, keyPath, object, change); 
} 

具体的に一部。

(void(*)(id,SEL,id,id,id))(m->method_imp)(owner, m->method_name, keyPath, object, change); 

私はObjective-CのとCに非常に新しいですし、二つの質問があり、このコンパイルエラーにerror: dereferencing pointer to incomplete type

を得る:上記の構文は何を

  1. と呼ばれているのですか?私はそれについてもっと読んでみたいです。
  2. どうすればその回線を機能させることができますか?

私はそれを理解していませんが、文章を2つ以上の行に分けて読みやすくすることができます。それが本当であれば、私はそれがどのように見えるかを見たいと思う。

答えて

2

これは、Objective-Cランタイム・ヘッダをインポートするような単純なことがあります

#import <objc/runtime.h> 

その後、コンパイラはMethodが何であるかを知っている、あなたはそれを参照解除に成功することができます。


(void(*)(id,SEL,id,id,id))(m->method_imp) 

タイプid,SEL,id,id,idの引数を持つ(ボイド)関数へのポインタであることm->method_impをキャスト。すべてのObjective-Cメソッドは実際にはC関数で、最初の引数はオブジェクトへのポインタ(selfを使用してアクセスできます)、2番目のメソッドは通常のメソッドのパラメータに従って、セレクタ(_cmdからアクセス可能)です。

このように、コンパイラは、2つの引数を使用してこの関数を持つことを主張します。したがって、この関数を通常のかっこで呼び出すことができます。オブジェクトを表す最初の引数、2番目のセレクタ、次にすべてのオブジェクト。

これについてもっと詳しく知るには、関数ポインタを検索し、Objective-Cランタイムの仕組みを学んでください。本質的には


、あなたはまた、次のコードを使用することもできます:

objc_msgSend(owner, m->method_name, keyPath, object, change); 

をしかし、その後、インスタンスメソッドを取得する必要はなかったでしょう。メソッドから必要なのは、すでに持っていたセレクタだけです。これは、コンテキスト引数として直接SELを使用して、コードを使用していたかもしれない、意味:m->method_impは次のように定義される程度IMPその後

objc_msgSend(owner, (SEL)context, keyPath, object, change); 

何か、:<objc/objc.h>

を、次のようにIMPが定義されています

typedef id   (*IMP)(id, SEL, ...); 

奇妙な構文のビットを、それはRではありませんので、どちらがそのタイプであり、どれがその定義であるかを明らかにする。まあ、この場合の定義はIMP、残りはid (*)(id, SEL, ...)です。これについてもっと知るには、いくつかの関数ポインタの記事を見てください。

だから、それはオブジェクト(id)を返し、複数の引数を取る関数へのポインタです:Objective-Cのものをデフォルトでは、おそらくいくつかのより多くの(追加の引数があるかもしれないことを意味する、...で表さ)

+0

ありがとう!私はすでにそのインポートを持っていましたが、Objective C 2.0ではstruct objc_methodが利用できないと言う作者から聞いてきました。しかし、セレクタをコンテキストとして渡してobjc_msgSendを使用することは、完璧に機能し、複数のパラメータを渡してNSNotificationのようなラッパーオブジェクトを回避できるという設計目標を達成します。それは非常に大きな+1! –

関連する問題