iOS底层学习-day-6

前言-OC语法篇

我是一名iOS开发者, iOS底层 菜鸟的进阶之路30天,这几天加班,没时间写和发布,趁着任务做完赶紧更新几篇。

问题

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

  • 有load方法
  • load方法在runtime加载类、分类的时候调用
  • load方法可以继承,但是一般情况下不会主动去调用load方法,都是让系统自动调用

load、initialize方法的区别什么?

  • 调用方式
    • load是根据函数地址直接调用
    • initialize是通过objc_msgSend调用
  • 调用时刻
    • load是runtime加载类,分类的时候调用(只会调用一次)
    • initialize是类第一次接收到消息的时候调用,每一个类智慧initialize一次(父类的initialize方法可能会被调用多次)

它们在category中的调用的顺序?

  • load
    • 先调用类的load
      • 先编译的类,优先调用load
      • 调用子类的load之前,会优先调用父类的load
    • 再调用分类的load
      • 先编译的分类,优先调用load
  • initialize
    • 先初始化父类
    • 再初始化子类(可能最终调用父类的initialize方法)

+ (void)load 调用

load是在runtime运行时的时候,就动态加载进来的,在分类中重写load方法,还是会先调用原来的load方法

  • 调用顺序

    • 先调用的+load 再调用分类的+load方法,按照编译先后顺序调用(先编译,先调用),调用子类的+load 之前会先调用父类的+load,如果父类已经调用过了,那么就不调用了,因为load只调用一次
    • 再调用分类的+load,按照编译先后顺序调用(先编译,先调用)
    • 为什么先加载父类的load方法,因为是将父类先加载方法列表前面,再放子类的load方法
  • +test 和 +load 方法的区别

    • 因为它直接调用类的+load了
    • 而自己写的+test方法是调用objc_msgSend([Person class],@selector(test))直接用消息机制调用,也就是isa一层一层往下找

+ initialize

  • 调用顺序
  • Class objc_getClass(const char *aClassName)
    • 先调用父类的+initialize,再调用子类的+initialize,因为内部有做先调用父类initialize,再调用子类initialize
objc_msgSend([MJPerson class], @selector(initialize));
objc_msgSend([MJStudent class], @selector(initialize));
  • (先初始化父类,再初始化子类,每个类只会初始化1次)
  • +initialize和+load
    • +initialize和+load的很大区别是,+initialize是通过objc_msgSend进行调用的,所以有以下特点:
      • 如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次)
      • 如果分类实现了+initialize,就覆盖类本身的+initialize调用
  • +initialize的原码分析类似于
 if (!sutdentInitialized) {
      if (!personInitialized) {
           objc_msgSend([MJPerson class], @selector(initialize));
           personInitialized = YES;
      }
      objc_msgSend([MJStudent class], @selector(initialize));
      sutdentInitialized = YES;
}
发布了12 篇原创文章 · 获赞 0 · 访问量 116

猜你喜欢

转载自blog.csdn.net/weixin_41732253/article/details/103782809