Ответ 1
Сообщение 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
для его отправки, что является обычной функцией отправки сообщений.
Дальнейшее чтение
Отъезд Майк Эш Пятница Q & A по этой теме.