【MJ底层课】OC对象的分类

269 阅读2分钟

概述

前几天,针对一道面试题分析了一下OC对象的本质。如果有兴趣可以去看一下。全篇其实讲的就是实例对象

objc的对象主要可以分为3种:

  • instance对象(实例对象)
  • class对象(类对象)
  • meta-class对象(元类对象)

本文只分析这几种对象,涉及到的isa方面的会另开一篇博客专门分析。

instance

  • instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象。

  • instance对象在内存中存储的信息包括:

    • isa指针
    • 其他成员变量

instance_obj.png

class

  • 我们可以通过很多方法来获取一个类对象:

    • 实例对象调用-class方法:
    Class obj_class = [obj1 class];
    
    • 类调用+class方法:
    Class obj_class2 = [NSObject class];
    
    • 通过Runtime API:
    Class obj_class3 = object_getClass(obj1);
    

这些方法获取的都是同一个对象,每个类在内存有且只有一个class对象。

  • class对象在内存中储存信息主要包括:
    • isa指针
    • superclass指针
    • 类型的属性信息(@property),类的实例方法信息(instance method)
    • 类的协议信息(protocal),类的成员变量(ivar)

class_obj.png

meta-class

meta-class被称为元类对象。每个类的内存中有且只有一个meta-class对象。

meta-class对象中存储的信息主要包括:

  • isa指针
  • superclass指针
  • 类的类方法信息(class method)

meta-class_obj.png

meta-class也是Class类型的,所以meta-class对象和Class对象的内存结构都是一样的。存储的信息不同就是说相关的成员变量为nil而已。

class对象和metaClass.png

相关的API

  • 获取:

    object_getClass(id obj)函数同样也可以用来获取meta-class。

    //获取Class对象
    Class cls = [NSObject class];
    NSLog(@"%p",cls);//0x7fff93c6f118
    //获取metaClass对象
    Class metaClass = object_getClass([NSObject class]);
    NSLog(@"%p",metaClass);//0x7fff93c6f0f0//这种方式只能获取Class对象,获取不到metaClass对象
    Class class = [[NSObject class] class];
    NSLog(@"%p",class);//0x7fff93c6f118
    
  • 判断:

    可以通过Runtime APIclass_isMetaClass()判断

    Class cls = [NSObject class];
    NSLog(@"%d",class_isMetaClass(cls));//0
    ​
    Class metaClass = object_getClass([NSObject class]);
    NSLog(@"%d",class_isMetaClass(metaClass)); //1
    

Object_getClass

在获取class对象和元类对象中,我们都使用了object_getClass(id obj)这个API。

总结一下:

NSObject *obj = [[NSObject alloc] init];
//传入instance对象返回class对象
Class cls = object_getClass(obj);
NSLog(@"%d",class_isMetaClass(cls));//0
//传入class对象返回meta-class对象
Class metaCls = object_getClass(cls);
NSLog(@"%d",class_isMetaClass(metaCls));//1