OC底层

该文章属笔者原创, 未经允许, 禁止转载

OC中的类

  1. instance 实例类
  2. class 类
  3. meta-class 元类

类的底层实现是struct, 比如NSObject实例类型的实现:

struct NSObject_IMPL {
    Class isa
}

继承自NSObject的HLPerson实例类型

struct HLPerson_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _age;
}

查看对象所占空间, 常用的几个命令

  • runtime中的class_getInstanceSize([NSObject class]), 创建一个实例对象, 至少需要多少内存空间
  • 中的malloc_size((__bridge const void *)obj), 创建一个实例对象,实际上分配了多少内存

各种类的结构

  1. instance:
    • isa指针
    • 其他成员变量(值)
  2. class: 可以通过class/objc_class/object_class方法获取
    • isa指针
    • superclass指针
    • 属性信息(@proprety)
    • 对象方法信息
    • 协议信息
    • 成员变量信息(ivar)
  3. meta-class: 通过object_class方法获取, 传入的对象必须是class
    • isa指针
    • superclass指针
    • 类方法信息

instance中不存放方法信息, 对象方法(减号方法)存放在class中, 类方法(加号方法)存放在meta-class中

方法调用

OC中的方法调用, 实质是发消息, 使用的是objc_msgSend(receiver, selector, arg1, arg2, ...)

可以看出, 其实, 底层在调用方法的时候, 其他是不知道是加号方法还是减号方法的, 因为他只接收了一个方法对象和一个方法名称

OC中的方法调用跟isa指针superclass指针息息相关

  1. 调用实例方法

    1. 通过instanceisa指针找到这个类的Class类, Class类中存放着实例方法, 如果没找到, 进行下一步
    2. 通过Class类superclass指针, 找到Class类的父类, 也是一个Class类, 依次向上查找
    3. 直到Root Class都没有找到的话, 由于Root Classsuperclass指向nil, 这时候就会报错说不识别方法
  2. 调用类方法

    1. 通过instanceisa指针找到这个类的Class类, 再根据Class类isa指针找到该类的meta-class类, 这里存放着类方法, 若没找到, 进入下一步
    2. 通过meta-class类superclass指针, 找到meta-class类的父类, 也是一个meta-class类, 依次向上查找
    3. 直到Root meta-class都没有找到的话, 由于Root meta-classsuperclass指向Root Class, 再在这里找一次方法, 如果没有找到, 这时候就会报错说不识别方法

调用实例方法调用类方法的差别在于第3步

OC底层_第1张图片
image

类方法的调用会多查找一步, 那就是找到Root meta-class对应的Root Class, 这时候, 如果在Root Class中实现一个同名的对象方法(减号方法), 同样会调用成功, 这就是之前为什么说, 在发消息的时候, 底层不知道是实例方法还是类方法

你可能感兴趣的:(OC底层)