让我们想象一下,我们有两个类:
@interface First : NSObject
@end
@interface Second : NSObject
@end
@implementation First
+(void)load
{
NSLog(@"This must be called first");
}
@end
@implementation Second
+(void)load
{
NSLog(@"And this must be called second");
}
@end
每个类中都有+load
个方法。如果我们运行此代码,This must be called first
将是第一个,And this must be called second
将是第二个。
什么决定了此类的+load
方法的调用顺序?在实验中,如果我在第一类的@implementation
之前移动第二类的@implementation
-首先打印And this must be called second
,然后打印This must be called first
。这是否意味着+load
的顺序仅取决于源代码中的顺序?
在我的实际情况下,我已经使用自定义+load
预编译了框架(某些代码在main()
之前被调用,并且从中看到了日志),我需要在此代码之前执行我的代码(我了解-我可以将其放入+load
,但我不知道如何更改顺序。还是我可以使用其他技术在框架代码之前调用我的代码?
答案 0 :(得分:2)
您真的不能依靠订单,也不能有效地控制订单。通过设计。 +load
应该在该类的+initialize
之前发生,但是在多个类中,两者的顺序似乎不确定(我觉得有些奇怪,但完全符合规则)。
这是为什么您不应该对+load
或+initialize
做任何繁重工作的重要原因。实际上,仅应谨慎使用它们,并且仅用于初始化一小部分高度本地化的状态。接触其他重要子系统很危险,因为您将以可能破坏系统的方式更改初始化顺序和行为。不应该,但是可以,过去也可以。
相反,您确实应该尝试在客户端明确调用的框架代码中有一个“从这里开始”的点。
答案 1 :(得分:2)
+load
方法是objc运行时在图像加载过程中调用的(您可以通过破坏load
方法并打印堆栈跟踪信息来看到它。)
+load
方法的调用顺序似乎取决于clang生成的objc类列表的顺序。
如果查看objc运行时的源代码,您会看到load_images
(由dyld调用的函数)调用prepare_load_methods
以获取图像中所有objc类的列表。 。 prepare_load_methods
调用_getObjc2NonlazyClassList
,这会从图像的__objc_nlclslist
部分中获取objc类列表。
load_images
然后调用call_load_methods
,它将遍历所有已加载的类并调用其+load
方法。