+ initialize和+ load以什么顺序调用?

时间:2018-12-30 00:17:36

标签: objective-c runtime objective-c-runtime

让我们想象一下,我们有两个类:

@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,但我不知道如何更改顺序。还是我可以使用其他技术在框架代码之前调用我的代码?

2 个答案:

答案 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方法。