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
метод.