美文网首页
iOS runtime

iOS runtime

作者: 奔跑吧小蚂蚁 | 来源:发表于2021-12-22 16:41 被阅读0次

    runtime 是 oc 语音的基础
    首先runtime的核心机制是消息机制 也就是oc的消息机制
    首先oc的消息机制可以分为五部分
    1 动态语言
    2 实例对象 类对象 元类对象之间的关系
    3 实例对象instance调用对象方法的过程链
    4 类对象调用类方法的过程链
    5 runtime objc_msgSend 函数 具体解析

    1 动态语言这块

    首先 从源代码到程序运行一般分为三个阶段 编译阶段 链接阶段 运行阶段
    oc 是动态 动态语音在编译阶段 链接阶段 不知道变量的数据类型 也不知道具体真正实现的那个方法 只有在运行时才会去检查 变量的数据类型 和 根据 方法名查找对应的方法进行实现 这样oc就可以把一些重要的工作从编译阶段 链接阶段 转移到运行阶段 这样就使o c具备更好的灵动性 而实现的的基础就是runtime
    而 在编译阶段 链接阶段 只需要进行 代码语法检验 还有就是生成运行时可执行的文件就可以了

    2 实例对象 类对象 元类对象之间的关系

    实例对象的isa指针指向类对象,类对象的isa指针指向元类对象,元类对象的isa指针指向基类元类对象。因为OC中类实质是一个结构体,除了isa指针,还包含superclass指针(实质都是NSObject的对象),还包含属性方法表等。类是对数据以及方法的封装,所以这三者的关系链也就由isa指针链接起来了。
    另外还有就是 类的成员变量 实例方法 归属实例对象 类的类方法归属在原类中 归属该类对象

    struct objc_class {
    Class _Nonnull isa; // 指向所属类的指针(_Nonnull)
    Class _Nullable super_class; // 父类
    const char * _Nonnull name; // 类名(_Nonnull)
    long version; // 类的版本信息(默认为0)
    long info; // 类信息(供运行期使用的一些位标识)
    long instance_size; // 该类的实例变量大小
    struct objc_ivar_list * _Nullable ivars; // 该类的成员变量链表
    struct objc_method_list * _Nullable * _Nullable methodLists; // 方法定义的链表
    struct objc_cache * _Nonnull cache; // 方法缓存
    struct objc_protocol_list * _Nullable protocols; // 协议链表
    } ;

    3 实例对象instance调用对象方法的过程链

    通过实例对象instance的isa指针找到类对象class,找到即调用
    如果找不到,通过实例对象的instance中的superclass找到父类对象,通过父类对象的isa指针找到父类对象的类对象class,找到调用方法
    如果仍然找不到,那么系统会通过消息转发机制进行消息转发,走消息转发的响应链,最后如果都没有能够处理消息的方法的话,那么会抛出unselector 的异常

    4 类对象调用类方法的过程链

    通过类对象class isa指针找到元类对象meta-class,通过存储在元类对象的方法表查找对应的方法进行调用
    如果没有找到,那么通过class的superclass 指针找到父类superclass,然后通过父类的superclass的isa指针找到父类的元类对象super-meta-class,通过存储在父类的元类对象meta-class找到类对象进行调用。

    5 runtime在其中具体的函数及其作用

    Objective-C 语言 中,对象方法调用都是类似 [receiver selector]; 的形式,其本质就是让对象在运行时发送消息的过程。

    我们来看看方法调用 [receiver selector]; 在『编译阶段』和『运行阶段』分别做了什么?

    编译阶段:[receiver selector]; 方法被编译器转换为:
    objc_msgSend(receiver,selector) (不带参数)
    objc_msgSend(recevier,selector,org1,org2,…)(带参数)
    运行时阶段:消息接受者 recevier 寻找对应的 selector。
    通过 recevier 的 isa 指针 找到 recevier 的 Class(类);
    在 Class(类) 的 cache(方法缓存) 的散列表中寻找对应的 IMP(方法实现);
    如果在 cache(方法缓存) 中没有找到对应的 IMP(方法实现) 的话,就继续在 Class(类) 的 method list(方法列表) 中找对应的 selector,如果找到,填充到 cache(方法缓存) 中,并返回 selector;
    如果在 Class(类) 中没有找到这个 selector,就继续在它的 superClass(父类)中寻找;
    一旦找到对应的 selector,直接执行 recevier 对应 selector 方法实现的 IMP(方法实现)。
    若找不到对应的 selector,消息被转发或者临时向 recevier 添加这个 selector 对应的实现方法,否则就会发生崩溃。
    在上述过程中涉及了好几个新的概念:objc_msgSend、isa 指针、Class(类)、IMP(方法实现) 等,下面我们来具体讲解一下各个概念的含义。

    相关文章

      网友评论

          本文标题:iOS runtime

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