一、对象的种类
OC中对象分为三种:
instance对象(实例对象):
通过类alloc出来的对象是实例对象, 每次alloc都会生成一个新的实例对象.
实例对象主要存储的信息包括: isa指针, 其他成员变量等
class对象(类对象):
类对象在内存中只会存储一份.
类对象主要存储的信息包括: isa指针, superclass 指针, 类的属性信息, 类的对象方法, 类的协议信息, 类的成员变量信息等
meta-class(元类对象):
元类对象与类对象的结构类似, 在内存中也只有一份
元类对象主要存储的信息包括: isa指针, superclass指针, 类的类方法等
二、类对象的源码分析
在objc源码中, 我们可以找到类对象的实现代码, 核心代码如下:
struct objc_class : objc_object {
// Class ISA; isa指针 继承自objc_object
Class superclass; // superclass 指针
class_data_bits_t bits; // 核心信息
class_rw_t *data() const {
return bits.data();
}
// .... 其他代码
};
复制代码
我们可以看到, data()函数返回的是 class_rw_t 类型, 继续探究
struct class_rw_t {
// ...
private:
// 获取当前类 是ro 或者是 rwe
const ro_or_rw_ext_t get_ro_or_rwe() const {
return ro_or_rw_ext_t{ro_or_rw_ext};
}
// ...
public:
// rw 的扩展
class_rw_ext_t *ext() const {
return get_ro_or_rwe().dyn_cast<class_rw_ext_t *>(&ro_or_rw_ext);
}
// 获取当前类的 class_rw_ext_t, 在Category加载时用到
class_rw_ext_t *extAllocIfNeeded() {
auto v = get_ro_or_rwe();
if (fastpath(v.is<class_rw_ext_t *>())) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext);
} else {
return extAlloc(v.get<const class_ro_t *>(&ro_or_rw_ext));
}
}
// ro 成员变量
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);
}
// 根据 ro_or_rwe(), 返回rw_ext的methods成员 或 ro_t 的baseMethods
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()};
}
}
// 根据 ro_or_rwe(), 返回rw_ext的properties成员 或 ro_t 的baseProperties
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};
}
}
// 根据 ro_or_rwe(), 返回rw_ext的protocols成员 或 ro_t 的baseProtocols
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};
}
}
// ...
};
复制代码
那么我们看下 class_rw_ext_t 分别是什么class_ro_t
// class_rw_ext_t
struct class_rw_ext_t {
class_ro_t_authed_ptr<const class_ro_t> ro; // class_ro_t
method_array_t methods; // 方法列表
property_array_t properties; // 属性列表
protocol_array_t protocols; // 协议列表
// ...
};
// class_ro_t
struct class_ro_t {
// ...
void *baseMethodList; // 方法列表
protocol_list_t * baseProtocols; // 协议列表
const ivar_list_t * ivars; // 成员变量列表
property_list_t *baseProperties; // 属性列表
// ...
};
复制代码
可以看到, 类对象的主要信息, 都存在了 class_rw_ext_t 和 class_ro_t 两个结构体中
三、isa指针, superclass指针分析
-
isa指针:
object_getClass
函数返回的就是isa指针, 我们可以通过这个函数来分析Class object_getClass(id obj) { if (obj) return obj->getIsa(); else return Nil; } 复制代码
- Person相关isa指针
- NSObject相关isa指针
根据我们的实验, 可以总一下:
实例对象的isa -> 类对象, 类对象的isa -> 元类对象
元类对象的isa -> 根元类(NSOject) 根元类的isa -> 自身
- superclass指针
总结如下:
子类的superclass -> 父类对象
父类对象的superclass -> NSObject
NSObject的superclass -> nil
- isa 和superclass 指针的总结图如下:
-
方法调用顺序
根据isa指针的指向, 我们就可以猜到, iOS 方法的调用顺序如下:
- 实例方法:
实例对象的isa指针指向类对象, 所以先在类对象的methods列表中找, 找不到则去类对象的superclass中找, 最终到找到NSObject
- 类方法:
类对象的isa指针指向元类对象, 所以先在元类对象的methods列表中找, 找不到则去元类对象的superclass中找, 最终找到NSObject
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END