+load
调用时机
load方法是在程序启动后执行main函数之前Runtime加载类和分类信息时候执行的而且是只调用一次!
调用流程
准备阶段
->先找到所有的类按照编译顺序放到数组classList中(先编译的在前,后编译的在后)
->在找到所有的分类按照编译顺序方法数组categoryList中(先编译的在前,后编译的在后)
->遍历classList中每个类,将含有load方法每个类加入到数组loadable_classes中,遍历过程中使用递归的方式:有父类的先将父类加入到数组loadable_classes中。
->遍历categoryList中每个分类,将含有load方法每个分类类加入到数组loadable_categories中。
调用阶段:
->先遍历loadable_classes,调用每个类中的load方法。
->再遍历loadable_categories ,调用每个分类中的load方法。
总结
先调用类中的load方法:按编译先后顺序调用(先编译先调用),调用子类的load方法之前先调用父类的。
再调用分类的load方法:按编译先后顺序调用(先编译先调用)。
+initialize
调用时机
+initialize是在类第一次接收到消息时调用。
调用顺序
先调用父类的在调用子类的initialize
内部实现原理
给类第一次发消息时,首先是通过isa找到对应的类对象,去类对象中查找方法实现,在查到方法实现调用之前,会先判断类对象是否需要初始化,如果需要初始化且之前没有初始化过就会调用 _class_initialize
方法,该方法内部使用了递归的方式判断了是否有父类且父类是否已经初始化,如果有父类且父类尚未初始化就先调用父类的initialize
方法(objc_msgSend()
),再去调用子类的。否则直接调用子类的initialize
方法。
+initialize特点
+initialize是通过objc_msgSend消息机制的方式调用所以有以下特点:
•分类中的initialize会覆盖原来类中的initialize方法
•如果子类没有实现+initialize方法会调用父类中的initialize方法(父类中的+initialize方法会调用多次)
+load与+initialize区别总结
调用方式
load是根据函数地址直接调用;
initialize是通过objc_msgSend调用
调用时刻
load是在程序启动后main函数之前Runtime加载类和分类信息的时候调用
initialize是在类第一次接收到消息时调用,每个类只会initialize一次(父类的initialize方法可能调用多次)
调用顺序
load:
先调用类中的load方法:按编译先后顺序调用(先编译先调用),调用子类的load方法之前先调用父类的。
再调用分类的load方法:按编译先后顺序调用(先编译先调用)。
initialize:先调用父类的在调用子类的initialize
网友评论