类的结构分析
引子:在程序世界中,无论接触哪门语言,类是最基本一个研究点。那么在oc中,类和类的结构是如何组成的呢?
类的isa走位图
avatar- 实例对象的isa指向类
- 类对象的isa指向元类
- 元类对象的isa指向根元类
- 根元类对象的isa指向自己本身
另外从继承角度看: - 子类subclass继承父类superclass;父类superclass继承根类rootclass(根类);根类rootclass继承nil
- 子类的元类继承父类的元类;父类的元类继承根类的元类;根类的元类继承根类;
通过clang命令,生成xxx.cpp文件
clang -rewrite-objc LGPerson.m -o LGPerson.cpp
struct LGPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
short _aa;
short _bb;
short _cc;
};
struct NSObject_IMPL {
Class isa;
};
typedef struct objc_class *Class;
//objc-runtime-new.h
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();
}
...
...
//objc-private.h
struct objc_object {
private:
isa_t isa;
- 通过分析xxx.cpp和objc4-781源码文件分析,我们可以得出以下一些信息。
- 在oc上层,所有类都是继承自NSObject。但是到了底层(c/c++)则是objc_class、objc_object;
- 所有的类都是以objc_class为模板继承来的;所有对象都是以objc_object为模板继承来的。
- 所有的对象、类、元类都有isa指针,万物皆对象。
- 类在内存中只存在一份
objc_object、objc_class、isa关系图
-w1273- id=objc_object:isa_t、关于isa相关操作、弱引用相关、关联对象、内存管理
- class=objc_class:objc_class继承自objc_object,Class superclass,cache_t cache,class_data_bits_t bits.
- isa_t 共用体,64位,分为指针型isa,全部位数为指针地址;非指针型isa,部分位数为指针地址。
- class_data_bits_t:主要是对class_rw_t的封装,class_rw_t是类读写(protocol、propertys、methods)相关信息,对class_ro_t的封装
(lldb) p/x LGPerson.class
(Class) $0 = 0x0000000100003420 LGPerson
(lldb) x/4gx 0x0000000100003420
0x100003420: 0x00000001000033f8 0x0000000100335140
0x100003430: 0x000000010066d6b0 0x0002802400000003
(lldb) p (class_data_bits_t *)0x100003440
(class_data_bits_t *) $1 = 0x0000000100003440
(lldb) p $1->data()
(class_rw_t *) $2 = 0x000000010066d630
(lldb) p *$2
(class_rw_t) $3 = {
flags = 2148007936
witness = 1
ro_or_rw_ext = {
std::__1::atomic<unsigned long> = 4294980072
}
firstSubclass = nil
nextSiblingClass = NSUUID
}
(lldb) p $3.properties()
(const property_array_t) $4 = {
list_array_tt<property_t, property_list_t> = {
= {
list = 0x0000000100003320
arrayAndFlag = 4294980384
}
}
}
(lldb) p $4.list
(property_list_t *const) $5 = 0x0000000100003320
(lldb) p *$5
(property_list_t) $6 = {
entsize_list_tt<property_t, property_list_t, 0> = {
entsizeAndFlags = 16
count = 1
first = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
}
}
(lldb) p $3.methods
(const method_array_t) $7 = {
list_array_tt<method_t, method_list_t> = {
= {
list = 0x0000000100003230
arrayAndFlag = 4294980144
}
}
}
Fix-it applied, fixed expression was:
$3.methods()
(lldb) p $7.list
(method_list_t *const) $8 = 0x0000000100003230
(lldb) p *$8
(method_list_t) $9 = {
entsize_list_tt<method_t, method_list_t, 3> = {
entsizeAndFlags = 26
count = 4
first = {
name = "sayHello"
types = 0x0000000100001f7d "v16@0:8"
imp = 0x0000000100001cc0 (KCObjc`-[LGPerson sayHello])
}
}
}
(lldb)
网友评论