+load && +initialize 作用、加载次序(Category)
+load
+load 定义
Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
通过关键字可以看出
- 作用:“perform class-specific behavior upon loading” 在类加载前执行类的一些行为
- 条件:“whenever a class or category is added” 在类中或者分类中添加(被加载时)就会被调用,猜测:这里如果为了优化,应该在编译期间,就把实现+load的类通过放在某个列表中,然后依次执行,或者在类中有个标记。为什么不是Cocoa中比较流行的注册机制,因为被加载时,运行时系统是“脆弱”的,只加载了基本的框架(Foundation),详见下文。
- 方式:“runtime” 也是通过运行时进行加载。看下面的“message”
The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.
当类或者分类可以响应load方法时,才发送load消息,但此时该类已经动态加载和静态链接的。
关于+load加载时机
- 程序初始化步骤:
The order of initialization is as follows:
All initializers in any framework you link to.
All +load methods in your image.
All C++ static initializers and C/C++ attribute(constructor) > functions in your image.
All initializers in frameworks that link to you.
但是这个2 和 3 的顺序是跟WWDC 2016 相反的
但是总体都是说初始化FrameWork → +load → main()函数 → 类的 initialize 方法 → 根据生命周期调用类的其他方法.
其中image的意思是:资源(WWDC 2016)
File Types:
Executable—Main binary for application
Dylib—Dynamic library (aka DSO or DLL)
Bundle—Dylib that cannot be linked, only dlopen(), e.g. plug-ins
Image—An executable, dylib, or bundle
+load的次序
A class’s +load method is called after all of its superclasses’ +load methods.
A category +load method is called after the class’s own +load method.
- 对于子类和父类,类和分类的调用顺序已经写明:
1、先调用超类的+load ,在调用子类的+load;
2、先调用完所有类的+load,在调用分类的+load。
- 那么其他文件的+load调用顺序是怎么样的?
[图片]
与 Build Phases 中的 Compile Sources 顺序一致。
同一个类的分类调用顺序是怎么样的?
与 Build Phases 中的 Compile Sources 顺序一致。
- 概括:
1、先调用超类的+load ,在调用子类的+load
2、先调用完所有类的+load,在调用分类的+load,即分类的+load总是会放在最后类的后面
3、按照Compile Sources 顺序执行
+load的注意事项:
In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.
- 在+load方法中,我们可以安全的给不相关的类发消息,但是+load方法中不应该调用他们
Custom implementations of the load method for Swift classes bridged to Objective-C are not called automatically.
swift 桥接到OC的混合编程中,swift的自定义的+load实现 不会自动调用。
因为+load在启动前就加载运行,过度的使用会影响首页加载时间
+initialize
时机:类第一次被调用时
Initializes the class before it receives its first message.
执行顺序
父类 优先 子类调用 initialize
该类的方法在其他类+load时期被调用,那么initialize调用,而后该类的+load在调用,因此+initialize可以比+load先调用
category 的覆写效应对 load 方法无效,但对 initialize 方法有效。且按 Complile Sources 的顺序,后面的会覆盖前面的。
initialize是线程安全的,其他线程需要等待第一个执行完执行完之后在进行执行。可以理解为@synchronized(self),因此注意,在initialize中只进行必要初始化操作
父类的initialize会被调用多次,因此注意下副作用。因为存在子类没实现initialize或者子类主动调用initialize的情况
如果想避免,可以
initialize is invoked only once per class. If you want to perform independent initialization for the class and for categories of the class, you should implement load methods.
最后
+load 和 + initialize 只被调用一次,是指启动时runtime机制而言,他们也可以被当做普通的类方法被调用,但是一般别这么使用。
如果子类没有实现+load和+initialize, 会调用父类的+load和父类的initialize方法。
category 不会覆盖类的+load,但是会覆盖类的+initialize