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クラスオブジェクトに送信します。からメソッドを継承しても、メッセージをクラスオブジェクトに送信しません。loadSubclassSubclassSuperclass
ランタイムは、クラスのすべてのスーパークラスオブジェクト(これらのスーパークラスオブジェクトがを実装している場合)およびリンク先の共有ライブラリ内のすべてのクラスオブジェクトにメッセージをload送信した後、メッセージをクラスオブジェクトに送信しloadますload。ただし、自分の実行可能ファイル内の他のどのクラスを受け取ったかはloadまだわかりません。
プロセスがアドレススペースにロードするすべてのクラスは、プロセスがクラスを他に使用しているかどうかに関係なくload、loadメソッドを実装している場合はメッセージを受け取ります。
あなたは、ランタイムがアップどのように見えるかを確認することができますloadでの特殊なケースのような方法を_class_getLoadMethodのobjc-runtime-new.mm、そしてから直接それを呼び出しますcall_class_loadsでobjc-loadmethod.mm。
ランタイムloadは、同じクラスの複数のカテゴリがを実装している場合でも、ロードするすべてのカテゴリのメソッドを実行しloadます。これは異常です。通常、2つのカテゴリが同じクラスの同じメソッドを定義する場合、メソッドの1つが「勝ち」、使用され、もう1つのメソッドは呼び出されません。
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;
}
このプログラムは、2行の出力を出力します。
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送信に使用していることがわかります。これは通常のメッセージ送信機能です。
参考文献
このトピックに関するマイクアッシュの金曜日のQ&Aをご覧ください。
+loadカテゴリごとに個別に送信されることに注意してください。つまり、クラスのすべてのカテゴリに独自の+loadメソッドが含まれている可能性があります。