美文网首页
06.Objective-C 分类(Categroy)的底层结构

06.Objective-C 分类(Categroy)的底层结构

作者: ProfessorFan | 来源:发表于2021-01-11 15:31 被阅读0次

问题

  1. Category 的底层结构
  2. 分类的加载处理过程
  3. 分类中load方法加载过程
  4. initialize方法的调用过程,准遵循原理
  5. initialize 方法 和 load 方法区别

答案

  1. Category 的底层结构
# 通过 
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc MJPerson+Test1.m -o MJPerson+Test1_arm64.cpp
得到了 category_t 分类的底层结构
struct _category_t {
    const char *name;
    struct _class_t *cls;
    const struct _method_list_t *instance_methods;
    const struct _method_list_t *class_methods;
    const struct _protocol_list_t *protocols;
    const struct _prop_list_t *properties;
};

# 通过 objc 源码  objc-runtime-new.h 文件中分类结构体的定义
struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;
    struct method_list_t *classMethods;
    struct protocol_list_t *protocols;
    struct property_list_t *instanceProperties;
    // Fields below this point are not always present on disk.
    struct property_list_t *_classProperties;

    method_list_t *methodsForMeta(bool isMeta) {
        if (isMeta) return classMethods;
        else return instanceMethods;
    }

    property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
    
    protocol_list_t *protocolsForMeta(bool isMeta) {
        if (isMeta) return nullptr;
        else return protocols;
    }
};
  1. 分类的加载处理过程
    分类函数加载到内存当中如下图:


    分类函数加载图.png
  • 在程序编译的时候,每一个分类(Category )都是一个Category_t 对象里面存储着所有的方法,协议,等
  • Category 中的方法,属性,协议数据 是在程序启动的时候通过runtime加载到内存道中去的,并合并到一个大数组中
    • 后编译的Category数据,会在数组的最前面
    • 当使用消息机制访问方法的时候,也就是后面编译的先访问,没有在找后面的如上图显示的访问顺序
  • 将合并后的分类数据(方法,协议,属性),插入到类原来数据的前面里面还涉及到两个方法 memmove,memcopy.
  1. 分类中load方法加载过程
  • +load方法会在runtime加载类和分类的时候调用(也就是程序启动的时候就会调用,在Main函数的前面)
  • 每个类,分类的 +load 方法,在程序运行过程中,只会主动的调用一次
  • 调用顺序:
    1. 先调动类的+load方法
      • 按照编译先后顺序调用(先编译,先调用)
    • 调用子类的+load之前会先调用父类的 +load 方法
    1. 再调用分类的 +load方法
  1. initialize方法的调用过程,准遵循原理
  • 调用顺序
    • 先调用父类的+initialize,在调用子类的 +initialize方法
    • 先初始化父类,再初始化子类,每一个类只会初始化一次
    • initialize 遵循消息机制原理
  1. initialize 方法 和 load 方法区别:
  • initialize:

    • 调用顺序是:先调用父类,在调用子类
    • 在类第一次接收到消息的时候调用
    • initialize 方法只调用一次,而且是被动调用
  • load:

    • 调用顺序是:先调用父类的load方法,在调用子类的laod方法,在调用分类的load方法
    • load 实在运行时加载类的时候调用的,也就是项目启动的时候调用的,调用时通过找到load 函数地址直接调 用的,而不是通过消息机制调用的.

相关文章

网友评论

      本文标题:06.Objective-C 分类(Categroy)的底层结构

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