メソッド

メソッド

Objective-C - メソッド

メソッドのリストにアクセスする

Keywords:class_nextMethodList

Class 型の構造体は、とうぜん、メソッドの定義も持っている。だけど、取り出すにはちょっと工夫が必要。Class 型の定義を見てみてくれ。メソッドの定義である、objc_method_list 型の methodLists というフィールドがあるんだけど、、、

/usr/include/objc/objc-class.h

struct objc_class {
 ...
 struct objc_method_list **methodLists;
 ...
};

ポインタのポインタになっていることからも想像できるように、こいつはメソッドのリストのリストだ。つまり、クラスのメソッドの定義は、複数のメソッドリストからできてるんだ。なんで、いくつかに分かれているのか?実行結果から推測すると、カテゴリごとに分かれているようだ(明確な記述がないから、あくまで推測)。

アクセスするには、専用の関数が用意されている(ポインタのポインタをインクリメントしてやっても、うまくいかなかった)。

/usr/include/objc/objc-class.h

OBJC_EXPORT struct objc_method_list *class_nextMethodList(Class, void **);

これを使えば、メソッドのリストのリストにアクセスできて、メソッドのリストを取り出すことができる。使用例は、こんな感じ。

showMethods() (sample)

 void* iterator = 0;
 struct objc_method_list* mlist;

 while(mlist = class_nextMethodList(klass, &iterator)) {
  Method method = mlist->method_list;
  ...
  }
}

これで、メソッドのリストである、Method 型の method_list を取り出すことができるんだ。





Objective-C - メソッド

メソッドのリストからメソッドを取り出す

Keywords: Method

上のようにして、メソッドのリストを得たら、そこからメソッドのリストを取り出す。Method の定義は、

/usr/include/objc/objc-class.h

typedef struct objc_method *Method;

であって、じゃあ struct objc_method の定義はどうか、っていうと、

/usr/include/objc/objc-class.h

struct objc_method_list {
 struct objc_method_list *obsolete;

 int method_count;
#ifdef __alpha__
 int space;
#endif
 struct objc_method {
  SEL method_name;
  char *method_types;
  IMP method_imp;
 } method_list[1]; /* variable length structure */
};

こうだ。method_count でメソッドの数を調べて、その数だけ method_list がある。そこから method_name とか method_types とかが得られるんだ。

method_name の型である SEL 型の定義は、/usr/include/objc/objc.h にある。

/usr/include/objc/objc.h

typedef struct objc_selector *SEL;

じゃあ、struct objc_selector の定義は、、、ないぞ!?見つからないー。公開してないのか?てなわけで、他のドキュメントを探ると、SEL は char へのポインタで、その先は C の文字列になってるらしい(『ところで、セレクタってなんなのさ?』の項を参照)。

というわけで、クラスから、メソッドの名前と型を取り出して表示する、サンプルコード。

showMethods() (sample)

void showMethods(Class klass)
{
 void* iterator = 0;
 struct objc_method_list* mlist;
 int i;

 printf("class: %s?", klass->name);

 while(mlist = class_nextMethodList(klass, &iterator)) {
  Method method = mlist->method_list;
  printf("method count: %d?", mlist->method_count);

  for(i = 0; i < mlist->method_count; i++) {
    printf(" method_name: %s?", (char*)method->method_name);
    printf(" method_types: %s?", method->method_types);
    method++;
  }
 }
}

これでメソッドの名前は分かる。次の問題は、メソッドの型だな。