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для надсилання, що є звичайною функцією надсилання повідомлень.
Подальше читання
Ознайомтесь із п’ятницею та питаннями п’ятниці Майка Еша на цю тему.
+loadнадсилається окремо для категорій; тобто кожна категорія в класі може містити свій власний+loadметод.