OC的实例对象、类对象、元类对象的关系

turboksiOS287

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找父类


标准图示:

2361104-8aea191c39f04e80.png



相关文章

Runtime动态创建类

Runtime动态创建类

- (void)viewDidLoad {    [super viewDidLoad];    Class KSObj = objc_allocateClas...

iOS基于SceneKit的3D汽车改色

iOS基于SceneKit的3D汽车改色

基于SceneKit的汽车改色,需要修改模型文件可以去 https://www.turbosquid.com/ 自行下载,免费资源还挺多的。先上个效果图吧:核心代码: &...

iOS短视频开发之---AVPlayer

iOS短视频开发之---AVPlayer

基于原生的AVPlayer + ScrollView实现,包含视频播放、暂停、点赞动画实现。视频是采用的本地视频、需要网络视频请自行添加添加测试。添加方式:  //本地视频 &n...

iOS 仿抖音打卡美好中国

iOS 仿抖音打卡美好中国

效果图这几天打卡中国挺火的,刚好有点时间就想着看看能不能模仿一下。Scrollview + CADisplayLink 设置背景UILongPressGestureRecognizer长按手...

isKindOfClass和isMemberOfClass的区别

isKindOfClass和isMemberOfClass的区别

+ (BOOL)isMemberOfClass:(Class)cls {//    类的元类 与 传入类 对比    return object_getClas...

Runtime详解

Runtime详解

The Objective-C language defers as many decisions as it can from compile time and link time to runti...