Student代码:
@interface XKStudent : XKPerson {
@public int _testMember;
}
@property (copy, nonatomic) NSString *school;
@property (copy, nonatomic) NSString *grade;
@end
先看 转译之后的 _class_ro_t 源码:
static struct _class_ro_t _OBJC_CLASS_RO_$_XKStudent = {
0,
__OFFSETOFIVAR__(struct XKStudent, _testMember),
sizeof(struct XKStudent_IMPL),
0,
"XKStudent",
(const struct _method_list_t *)&_OBJC_$_INSTANCE_METHODS_XKStudent,
0,
(const struct _ivar_list_t *)&_OBJC_$_INSTANCE_VARIABLES_XKStudent,
0,
(const struct _prop_list_t *)&_OBJC_$_PROP_LIST_XKStudent,
};
之前已经整理过,_class_ro_t 会被 class_t 对象持有,class_t 关键在于 isa 和 superclass 两个指针和 cache。而 _class_ro_t 则主要管理 成员变量、方法、协议、属性。isa、superclass 等的设置会通过 class_setup 相关方法设置,具体源码就不贴出来了。
看的出来:
- _ivar_list_t 为:OBJC$_INSTANCE_VARIABLES_XKStudent,表示实例对象的成员变量;
- _prop_list_t 为:OBJC$_PROP_LIST_XKStudent,表示属性列表;
这就是 ivar 列表和属性列表;
_INSTANCE_VARIABLES_XKStudent:
static struct /*_ivar_list_t*/ {
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count;
struct _ivar_t ivar_list[3];
} _OBJC_$_INSTANCE_VARIABLES_XKStudent = {
sizeof(_ivar_t),
3,
{{&OBJC_IVAR_$_XKStudent$_testMember, "_testMember", "i", 2, 4},
{&OBJC_IVAR_$_XKStudent$_school, "_school", "@\"NSString\"", 3, 8},
{&OBJC_IVAR_$_XKStudent$_grade, "_grade", "@\"NSString\"", 3, 8}}
};
_PROP_LIST_XKStudent:
static struct /*_prop_list_t*/ {
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count_of_properties;
struct _prop_t prop_list[2];
} _OBJC_$_PROP_LIST_XKStudent __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_prop_t),
2,
{{"school","T@\"NSString\",C,N,V_school"},
{"grade","T@\"NSString\",C,N,V_grade"}}
};
总结:
- 属性是 ivar 的子集;
- 属性是通过编译器特性生成的,不仅添加到了成员变量,还添加了 setter 和setter 和 getter 以支持点语法;
- _xxx 则是直接追加到结构体中,不能使用点语法的;
网友评论