OC的实例对象、类对象、元类对象的关系
Objective-C中的对象、简称OC对象,主要分为三种:
instance对象(实例对象)、class对象(类对象)、meta-class对象(元类对象)。
一:instance对象
instance对象就是通过alloc出来的对象,每次调用alloc都会产生新的instance对象。
比如:
NSObject * obj1 = [[NSObject alloc] init];
NSObject * obj2 = [[NSObject alloc] init];
obj1、obj2是NSObject的instance对象对象(实例对象),他们是不同的两个对象,分别占用着不同的内存。
instance对象在内存中存储的信息包括:
isa指针
其他成员变量。
二:Class对象
NSObject * obj1 = [[NSObjectalloc]init];
NSObject * obj2 = [[NSObjectalloc]init];
Class cls1 = [obj1class];
Class cls2 = [obj2class];
Class cls3 = [NSObjectclass];
Class cls4 =object_getClass(obj1);
Class cls5 =object_getClass(cls2);
obj1 ~ cls5 都是NSObject的class对象(类对象)
他们是同一个对象。每个类在内存中有且只有一个class对象。
class对象在内存中存储的信息主要包括:
isa指针
superclass指针、类的属性信息(@property)
类的对象方法(instance method)
类的协议信息(protocol)
类的成员信息(ivar)
...
三:meta-class对象
Class metacls = object_getClass([NSObject class]);
metacls是NSObject的meta-class对象(元类对象)
每个类在内存中有且只有一个meta-class对象
meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括:
isa指针
superclass指针
类的类方法信息(class method)
...
注意点:
以下代码获取的cls是class对象,并不是meta-class对象。
Class cls = [[NSObject class] class];
查看Class是否为meta-class
#import <objc/runtime.h>
Class cls = object_getClass([NSObject class]);
BOOLresult =class_isMetaClass(cls);
四:isa指针
instance的isa指向class
当调用对象方法的时候,通过instance的isa找到class,然后找到对象方法的实现进行调用
class的isa指向meta-class
当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用
从64bit开始,isa需要进行一次位运算,才能计算出真实地址:
# if __arm64__
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE0x000001a000000001ULL
struct{
uintptr_t nonpointer :1; //0代表普通的指针、存储着Class、Meta-Class对象的内存地址。 1代表是优化过的isa指针、使用位域存储更多的信息
uintptr_thas_assoc :1; //是否设置过关联对象、没有的话释放更快
uintptr_t has_cxx_dtor :1; //是否有C++的析构函数(.cxx_destruct),没有的话释放更快
uintptr_t shiftcls :33; // MACH_VM_MAX_ADDRESS 0x1000000000 存储着Class、Meta-Class的内存地址信息
uintptr_tmagic :6; //用于在调试的时候分辨对象是否未完成初始化
uintptr_t weakly_referenced : 1; //是否有被弱引用指向过,没有的话释放的更快
uintptr_tdeallocating :1; //对象是否正在释放
uintptr_t has_sidetable_rc :1; //引用计数器是否过大无法存储在isa中。如果为1的话、那么饮用计数会存储在一个叫SideTable的类的属性中
uintptr_textra_rc :19; //里边存储的值是引用计数器-1
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
};
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# define ISA_MAGIC_MASK 0x001f800000000001ULL
# define ISA_MAGIC_VALUE0x001d800000000001ULL
struct{
uintptr_tnonpointer :1;
uintptr_thas_assoc :1;
uintptr_thas_cxx_dtor :1;
uintptr_t shiftcls :44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000
uintptr_tmagic :6;
uintptr_t weakly_referenced : 1;
uintptr_tdeallocating :1;
uintptr_t has_sidetable_rc :1;
uintptr_textra_rc :8;
# define RC_ONE (1ULL<<56)
# define RC_HALF (1ULL<<7)
};
# else
# error unknown architecture for packed isa
# endif
五:superclass指针
举例 1:
@interface Student :Person
@interface Person : NSObject
当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass指针找到Person的class,最后找到对象方法的实现进行调用。
举例 2:
@interface Student :Person
@interface Person : NSObject
当Student的class要调用Person的类方法的时候,会先通过isa找到Student的meta-class对象,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用。
文字总结:
1. instance的isa指向class
2. class的isa指向meta-class
3. meta-class的isa指向基类的meta-class
4. class的superclass指向父类的class
----如果没有父类,superclass指针为nil
5. meta-class的superclass指向父类的meta-class
----基类的meta-class的superclass指向基类的class
6. instance调用对象方法的轨迹
----isa找到class,方法不存在,就通过superclass找父类
7. class的调用类方法轨迹
----isa找meta-class,方法不存在,就通过superclass找父类
标准图示: