美文网首页OC原理知识
Category 庖丁解牛版

Category 庖丁解牛版

作者: MrBMask | 来源:发表于2018-12-21 18:41 被阅读0次

    一.Category的底层结构

    在runtime运行中都是一个category_t的一个结构体,里面包含{
    类名,
    对象方法列表,
    类方法列表,
    协议,
    实例化属性
    }


    Category的底层结.png

    二.Category的加载处理过程

    1.通过runtime加载某个类的所有Category的数据
    2.把所有category的方法,属性,协议数据合并到一个大数组中(后面参与编译的category数据会在数组的前面)
    3.将合并后的分类数据(方法,属性,协议),插入到类原来数据的前面

    • 导致:
      1.同样的方法有限调用分类的方法
      2.最后面参与编译的分类方法,优先调用

    三.Category 和 Class extension(匿名分类/类扩展)的区别

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

    四. +load 和 +initialize(匿名分类/类扩展)的区别

    +load方法

    1.会在runtime加载类,分类的时候调用
    2.每个类,分类的+load,在程序运行过程中只调用一次
    3.调用顺序:
    1>先调用类的load 先编译的类优先调用load,调用子类的load之前,会先调用父类的load
    2>在调用分类的load 先编译的分类,优先调用

    +initialize方法
    1. 会在类第一次接受到消息的时候调用
    2. 会先调用父类的+initialize的方法,再调用子类的方法(每个类只会初始化一次)

    区别:

    • 调用方式:
      load是根据函数地址直接调用
      initialize是通过objc_msgSend调用
    • 调用时刻:
      load是runtime加载类,分类的时候调用(只会调用一次)
      initialize是类第一次接收到消息时候会调用,每一个类只会initialize一次(父类的initialize可能会被调用多次)如果分类实现了+initialize就覆盖类本身的initialize调用

    五.分类可以添加成员变量吗?

    (添加之后只是声明了set和get方法,但是没有写成属性也没有实现set和get方法)
    默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中。但可以通过关联对象来间接实现

    • 关联对象提供了以下API

    • 添加关联对象
      void objc_setAssociatedObject(id object, const void * key,
      id value, objc_AssociationPolicy policy)

    • 获得关联对象
      id objc_getAssociatedObject(id object, const void * key)

    • 移除所有的关联对象
      void objc_removeAssociatedObjects(id object)

    相关文章

      网友评论

        本文标题:Category 庖丁解牛版

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