该load
消息
load
在将类对象加载到进程的地址空间后不久,运行时将消息发送到每个类对象。对于属于程序可执行文件一部分的类,运行时会load
在进程的生命周期的很早就发送消息。对于共享(动态加载)库中的类,运行时会在将共享库加载到进程的地址空间后立即发送加载消息。
此外,运行时仅load
在该类对象本身实现该load
方法的情况下才发送给该类对象。例:
@interface Superclass : NSObject
@end
@interface Subclass : Superclass
@end
@implementation Superclass
+ (void)load {
NSLog(@"in Superclass load");
}
@end
@implementation Subclass
// ... load not implemented in this class
@end
运行时将load
消息发送到Superclass
类对象。即使从继承方法,它也不会将load
消息发送到Subclass
类对象。Subclass
Superclass
在将load
消息发送load
到所有类的超类对象(如果实现了这些超类对象load
)以及您链接到的共享库中的所有类对象之后,运行时将消息发送到类对象。但是您不知道自己的可执行文件中还接收load
了哪些其他类。
如果进程load
实现了该load
方法,则您的进程加载到其地址空间中的每个类都会收到一条消息,无论您的进程是否对该类进行了其他任何使用。
你可以看到在运行时如何查找的load
方法作为一种特殊情况_class_getLoadMethod
的objc-runtime-new.mm
,并直接调用它call_class_loads
的objc-loadmethod.mm
。
运行时还会运行load
它加载的每个类别的方法,即使同一类上实现了多个类别load
。这很不寻常。通常,如果两个类别在同一类上定义了相同的方法,则其中一个方法将“获胜”并被使用,而另一个方法将永远不会被调用。
该initialize
方法
initialize
在将第一条消息(load
或initialize
除外)发送到类对象或任何类实例之前,运行时会在类对象上调用方法。该消息是使用常规机制发送的,因此,如果您的类未实现initialize
,但从继承该类的类继承,则您的类将使用其超类的initialize
。运行时将首先发送initialize
到所有类的超类(如果尚未发送initialize
)。
例:
@interface Superclass : NSObject
@end
@interface Subclass : Superclass
@end
@implementation Superclass
+ (void)initialize {
NSLog(@"in Superclass initialize; self = %@", self);
}
@end
@implementation Subclass
// ... initialize not implemented in this class
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
Subclass *object = [[Subclass alloc] init];
}
return 0;
}
该程序输出两行输出:
2012-11-10 16:18:38.984 testApp[7498:c07] in Superclass initialize; self = Superclass
2012-11-10 16:18:38.987 testApp[7498:c07] in Superclass initialize; self = Subclass
由于系统initialize
延迟地发送方法,因此除非您的程序实际将消息发送到该类(或子类,或该类的实例或子类的实例),否则一个类将不会收到消息。到您收到时initialize
,过程中的每个课程都应该已经收到load
(如果适用)。
规范的实现方式initialize
是:
@implementation Someclass
+ (void)initialize {
if (self == [Someclass class]) {
// do whatever
}
}
此模式的要点是避免Someclass
在子类未实现时重新初始化自身initialize
。
运行时initialize
在中的_class_initialize
函数中发送消息objc-initialize.mm
。您可以看到它objc_msgSend
用来发送消息,这是正常的消息发送功能。
进一步阅读
查阅Mike Ash的星期五有关该主题的问答。
+load
是针对类别单独发送的;也就是说,类中的每个类别都可以包含其自己的+load
方法。