Class 型の構造体のは、インスタンス変数のリストへのポインタを持っているんだ。こいつをたどっていけば、インスタンス変数を表示することができるぜ。
まずは Class 型を見てみよう。objc_ivar_list 型の ivars というフィールドがあるんだ。
順に追っていこう。まず、Class 型の定義は /usr/include/objc/obj.c にある。
/usr/include/objc/objc-class.h
struct objc_class {
...
struct objc_ivar_list *ivars;
...
};
これがインスタン変数のリストだ。objc_ivar_list の定義はこんな感じになっている。
/usr/include/objc/objc-class.h
struct objc_ivar_list {
int ivar_count;
#ifdef __alpha__
int space;
#endif
struct objc_ivar {
char *ivar_name;
char *ivar_type;
int ivar_offset;
#ifdef __alpha__
int space;
#endif
} ivar_list[1]; /* variable length structure */
};
ivar_count がインスタンス変数の数を表す。その数の分だけ、ivar_list の配列があるわけだ。ivar_list は objc_ivar 型であり、その中に、インスタンス変数の名前である ivar_name、インスタンス変数の型名である ivar_type とかがあるんだ。
クラスを指定して、その中のインスタンス変数を表示させるサンプルコードは、こんな感じになる。
showInstanceVariables() (sample)
void showInstanceVariables(Class klass)
{
struct objc_ivar_list* ivars;
Ivar ivar;
int i;
printf("class: %s?", klass->name);
ivars = klass->ivars;
if(ivars == nil) {
printf("There is no ivars?");
return;
}
// Show instance variables
ivar = ivars->ivar_list;
for(i = 0; i < ivars->ivar_count; i++) {
printf(" ivar name: %s?", ivar->ivar_name);
printf(" ivar type: %s?", ivar->ivar_type);
printf(" ivar offset: %d?", ivar->ivar_offset);
ivar++;
}
}
この関数に Class を引き渡してやると、中のインスタンス変数を走査して、名前と型名とオフセットを表示するんだ。実行結果は、こんな感じ。たとえば NSResponder を渡すと、
/usr/include/objc/objc-class.h
class: NSResponder
ivar name: _nextResponder
ivar type: @
ivar offset: 4
名前が _nextResponder っていうインスタンス変数が 1 つあって、その型名は @ だ。あとで説明するけど、@ は id 型を表しているんだ。