isa和superClass

Objective-C的本质

我们平时编写的Objective-C代码,底层实现其实都是C\C++代码,Objective-C的对象、类主要是基于C\C++的结构体实现的

调用关系.png

将Objective-C代码转换为C\C++代码:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件
如果需要链接其他框架,使用-framework参数。比如-framework UIKit

一个OC对象在内存中是如何布局的?
NSObject的底层实现.png

OC对象的分类主要分为三个大类

实例对象,instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象object1、object2是NSObject的instance对象(实例对象)
// instance对象,实例对象
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];

它们是不同的两个对象,分别占据着两块不同的内存
instance对象在内存中存储的信息包括

  • isa指针
  • 其他成员变量
实例对象地址.png
类对象objectClass1 ~ objectClass5都是NSObject的class对象(类对象)
// class对象,类对象
// class方法返回的一直是class对象,类对象
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];

它们是同一个对象。每个类在内存中有且只有一个class对象

class对象在内存中存储的信息主要包括

  • isa指针

  • superclass指针

  • 类的属性信息(@property)、类的对象方法信息(instance method)

  • 类的协议信息(protocol)、类的成员变量信息(ivar)
    ......

  • 类方法信息


    类对象结构.png
元类对象

每个类在内存中有且只有一个元类对象,元类对象和类对象的内存结构一样,但用途不一样。

元类对象在内存中存储的信息

  • isa指针
  • superClass的isa指针
元类对象结构.png
// meta-class对象,元类对象
// 将类对象当做参数传入,获得元类对象
Class objectMetaClass = object_getClass(objectClass5);
类的获取

Class objc_getClass(const char *aClassName)
传入字符串类名
返回对应的类对象

Class object_getClass(id obj)
传入的obj可能是instance对象、class对象、meta-class对象

返回值
如果是instance对象,返回class对象
如果是class对象,返回meta-class对象
如果是meta-class对象,返回NSObject(基类)的meta-class对象

(Class)class、+ (Class)class
返回的就是类对象

指针

isa

instance的isa指向class
当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用

class的isa指向meta-class
当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用

isa指针.png
supclass

supclass指针指向父类的类对象

class对象的superclass指针
当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用

class的supclass.png

meta-class对象的superclass指针
当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用


meta-class的superclass.png
占用内存

创建一个实例对象,至少需要多少内存?

#import 
class_getInstanceSize([NSObject class]);

创建一个实例对象,实际上分配了多少内存?

#import 
malloc_size((__bridge const void *)obj);

isa指针占用8个字节,_no占用4个字节,_age占用4个字节


student对象内部结构.png

总结

instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基类的meta-class

class的superclass指向父类的class,如果没有父类,superclass指针为nil
meta-class的superclass指向父类的meta-class,基类的meta-class的superclass指向基类的class

instance调用对象方法的轨迹,isa找到class,方法不存在,就通过superclass找父类
class调用类方法的轨迹,isa找meta-class,方法不存在,就通过superclass找父类

指针路径.png


ISA_MASK值.png

isa指向地址获取流程如下图


isa指向地址获取.png

  • 对象调用方法的轨迹

    通过isa指针指向类对象,在类对象的实例方法列表中找,如果没找到,通过superclass指针向父类里面找,若果都没有找到,则会报错:No known class method for selector

  • 类对象调用方法的轨迹

    和对象调用方的轨迹类似,只不过是对象通过isa找到类对象,类对象通过isa找到元类对象,依次向上找,找到基类元类对象里面,如果基类元类对象里面也没有的话,会去基类的类对象里面找

    举例说明:
    对象中没有类方法 +test(),但是父类中有实例方法 -test(),这个时候调用 [Person test],会依次向上查找,直到再父类类对象中找到实例方法,可以调用
    消息传递方式
    objc_msgSend([Person class], @selector(test))
    objc_msgSend(person, @selector(test))
    isa -> superclass -> suerpclass -> superclass -> .... superclass == nil
    

objc_object结构

objc_object结构.png
struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

当前使用的都是OBJC2,所以这段结构基本上废弃了,现在为以下结构:

struct objc_class {
    Class isa;
    Class superclass;
    cache_t cache;  //方法缓存,是个table
        class_data_bits_t bits;  //  用于获取具体的类信息,是个table
}

& FAST_DATA_MASK  之后获得

struct class_rw_t {
    uint32_t
        Class isa;
        Class superclass;
        cache_t cache;  //方法缓存,是个table
        class_data_bits_t bits;  //  用于获取具体的类信息,是个table
}

总结

  • 对象的指针指向哪里
    对象的isa指针指向类对象
    类对象的isa指针指向元类的类对象
    元类类对象的isa指针指向基类的元类类对象

  • OC的类信息存放在哪里
    实例对象方法、属性、成员变量(大小,类型,名字)、协议信息存放在类对象中
    类方法存放在元类对象中
    成员变量的具体值存放在实例对象

objc4源码下载

你可能感兴趣的:(isa和superClass)