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
ます。これは異常です。通常、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
メソッドが含まれている可能性があります。