【MJ-iOS底层原理总结】Category中的load和initialize

255 阅读1分钟
1. Category和Class Extension的区别是什么?
  • Class Extension在编译的时候,它的数据就已经包含在类信息中
  • Category是在运行时,才会将数据合并到类信息中
2. Category中的load方法是什么时候调用的?调用顺序是怎么样的?
  1. 进行验证
    • 建立Person类,再添加两个分类,都写上load方法。发现输出结果如下: image.png
    • 这和分类的方法先执行是有区别的,研究一下这是为什么呢?
    • 查看源码进行验证 image.png
    • 发现call_load_methods函数中,是先调用的本类的load方法,再调用的分类的load方法。
    • 再查看call_class_loads函数,发现其中是直接取load方法的地址进行调用。 image.png
    • 普通方法调用,是使用消息发送机制进行调用的。所以会先调用分类中的方法,找到对应方法后就不会再继续了。
  2. 调用顺序:
    1. 先调用的本类的+load方法
      • 按照编译先后顺序调用
      • 调用子类的+load之前,会先调用父类的+load
    2. 再调用的分类的load方法
      • 按照编译先后顺序调用
  3. load方法在runtime加载类、分类的时候调用
3. Category中的initialize方法是什么时候调用的?
  1. +initialize会在类第一次接收到消息时调用
  2. 调用顺序:先调用父类的+initialize,再调用子类的+initialize
  3. +initialize+load的很大区别是,+initialize是通过objc_msgSend进行调用的,所以有以下特点
    • 如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次)

    • 如果分类实现了+initialize,就覆盖类本身的+initialize调用