对象的isa 指向什么?
方法调用的本质是 runtime 的 objc_megSend(消息转发)
Person *person = [[Person alloc] init];
[person personInstanceMethod];
// ((void (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("personInstanceMethod"));
// objc_msgSend(person, @selector(personInstanceMethod));
[Person personClassMethod];
// ((void (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("personClassMethod"));
// objc_msgSend([Person class], @selector(personClassMethod));
复制代码
- instance 对象的isa 指向 class
- 当调用实例方法时,通过instance 的 isa 找到 class,最后找到对象方法的实现并调用
- class 的 isa 指向 meta-class
- 当调用类方法时,通过class 的isa 找到 meta-class,最后找到类方法的实现并调用
- meta-class 的 isa 指向基类的 meta-class
class 的superClass指针
肯定是跟继承有关系
@interface Person: NSObject
@interface Student: Person
复制代码
- 当 Student 的 instance 对象调用 Person 的对象方法时,会先通过 isa 找到Student 的class类对象,然后通过 superclass 找到 Person 的 class 类对象,最后找到对象方法的实现并调用;
- 当 Student 的 instance 对象调用 NSObject 的对象方法时,会先通过 isa 找打Student 的 class 类对象, 然后通过 superclass 找打 Person 的 class 类对象, 再通过 superclass 找到 NSObject 的 class 类对象, 最后找到对象方法的实现并调用
meta-class 对象的 superClass 指针
- 当 Student 的 class 要调用 Person 的类方法时,会想通过 isa 找到 Student 的 meta-class 元类对象, 然后通过 superclass 找到 Person 的 meta-class 元类对象,最后找到类方法的实现并调用;
- 当 Student 的 class 要调用 NSObject 的类方法时,会通过 isa 找到 Student 的 meta-class 元类对象, 然后通过 superclass 找到 Person 的 meta-class元类对象,然后通过 superclass 找到NSObject 的 meta-class 元类对象, 最后找到类方法的实现并调用
isa 和 superclass 总结
- instance实例对象 的isa 指向class类对象
- class类对象 的isa 指向 meta-class元类对象
- meta-class元类对象 的 isa 指向基类的 meta-class元类对象
- 基类 meta-class 的 isa 指向它本身
- class 的superclass 指向它父类的 class
- 如果没有父类,则指向nil
- meta-class 的superclass 指向父类的meta-class
- [重点] 基类的meta-class 的superclass 指向 基类的 class(为什么?)
- 因为 OC 中的方法是 msgSend,并不关心是否是类方法还是实例方法,只是匹配方法名称,所以基类的 class 对象中如果有实例方法名和调用的类方法名重名,也照样能调用
- instance 调用方法轨迹
- isa 找到 class,方法不存在,通过superclass 找父类
- class 调用方法轨迹
- isa 找到meta-class,方法不存在,通过superclass 找父类
关于 isa 指向问题
//
# if __arm64__
# define ISA_MASK 0x007ffffffffffff8ULL
# else
# define ISA_MASK 0x0000000ffffffff8ULL
复制代码
- 在32位机器上,instance 对象的 isa 直接指向的是就是类对象的实现
- 在64位机器上,instance 对象的 isa 需要先进行一次与运算ISA_MASK,其结果指向的是类对象的实现
0xxxxx & 0x007ffffffffffff8
关于superclass 指向问题
- 子类的superclass 直接指向的就是 父类的实现,不会经过任何运算
类对象源码
struct objc_object {
private:
isa_t isa;
}
// 最新版本中的体现
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() const {
return bits.data();
}
}
// class_readwrite_table {}
struct class_rw_t {
// readonly - 这里包含了 类名及成员变量信息
const class_ro_t *ro() const {
auto v = get_ro_or_rwe();
if (slowpath(v.is<class_rw_ext_t *>())) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->ro;
}
return v.get<const class_ro_t *>(&ro_or_rw_ext);
}
// 方法列表信息
const method_array_t methods() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->methods;
} else {
return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseMethods()};
}
}
// 属性列表信息
const property_array_t properties() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->properties;
} else {
return property_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProperties};
}
}
// 代理信息
const protocol_array_t protocols() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->protocols;
} else {
return protocol_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProtocols};
}
}
}
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize; // 实例变量需要的内存大小
#ifdef __LP64__
uint32_t reserved;
#endif
union {
const uint8_t * ivarLayout;
Class nonMetaclass;
};
explicit_atomic<const char *> name; // 类名
// With ptrauth, this is signed if it points to a small list, but
// may be unsigned if it points to a big list.
void *baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars; // 成员变量信息
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END