美文网首页
Category的实现原理

Category的实现原理

作者: 39Coding | 来源:发表于2020-06-30 13:23 被阅读0次

    Category的实现原理。

    • Category编译之后的底层结构是struct category_t,里面存储着分类的实例方法类方法属性协议信息
    • 在程序运行的时候,Runtime会将Category的数据,合并附加到类信息中(class对象、meta-class对象)
    • PS1:Runtime将分类的方法放在原来的方法的前面,因此分类的方法优先级更高,所以如果有重名的方法,会优先调用分类的方法
    • PS2:如果多个分类有重名的方法,【后】编译的分类的方法优先级更高,因为Runtime里面的方法列表附加操作的顺序是下标从大到小进行的,越往后越靠前
    • PS3:在 Tatgets -> Build Phases -> Compile Sources 中可以控制编译顺序,编译是从上到下的顺序,想调用的优先级高的就往下放
    Category底层结构.jpg Category加载过程.jpg

    Category和Class Extension的区别是什么?

    • Class Extension在编译的时候,它的数据就已经包含在类信息中
    • Category是在运行时,才会将数据合并到类信息中

    Category中有load方法吗?load方法是什么时候调用的?load方法能继承吗?

    • 有。
    • load方法在Runtime加载类、分类的时候调用
    • load方法可以继承,在子类没有重写load方法,主动去调用load方法(消息发送机制)时会调用父类的load方法,说明是有继承关系的,但是一般情况下不会主动去调动load方法,都是让系统自动调用(在Runtime加载时是直接拿到load方法的地址去调用,之后手动调用时其实就是利用消息发送机制:子类没有load方法就会去父类的方法列表里面找)

    load、initialize方法的区别是什么?它们在Category中的调用的顺序?以及出现继承时它们之间的调用过程?

    • 区别:
    • 调用方式

    load是根据函数地址直接调用
    initialize是通过objc_msgSend调用

    • 调用时刻

    loadRuntime加载(所有参与编译的)类、分类的时候调用,只会调用1次
    initialize是类第一次接收到消息的时候调用,每一个类只会调用initialize一次,但父类的initialize方法可能会被调用多次(例如:子类和子类的分类都没有实现initialize方法时就会去调用父类的initialize方法)

    • 调用顺序

    load
    先调用类的load
    先编译的类,优先调用load
    调用子类的load之前,会先调用父类的load
    再调用分类的load
    先编译的分类,优先调用load

    initialize
    调用父类的initialize(初始化)
    再调用子类的initialize(初始化)

    可能最终调用的是父类的initialize(子类没有实现initialize

    Category能否添加成员变量?如果可以,如何给Category添加成员变量?

    • 不能直接给Category添加成员变量,但是可以间接实现Category有成员变量的效果关联对象
    objc_AssociationPolicy对应表.jpg Runtime关联对象关系图.jpg

    相关文章

      网友评论

          本文标题:Category的实现原理

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