OC底层

作者: Homer1ynn | 来源:发表于2018-07-10 16:13 被阅读27次

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

    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/malloc.h>中的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步

    image

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

    相关文章

      网友评论

          本文标题:OC底层

          本文链接:https://www.haomeiwen.com/subject/xyfqpftx.html