该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类对象。SubclassSuperclass
在将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方法。