loadwiadomość
Środowisko wykonawcze wysyła loadkomunikat do każdego obiektu klasy, wkrótce po załadowaniu obiektu klasy do przestrzeni adresowej procesu. W przypadku klas, które są częścią pliku wykonywalnego programu, środowisko wykonawcze wysyła loadkomunikat na bardzo wczesnym etapie życia procesu. W przypadku klas, które znajdują się we współużytkowanej (ładowanej dynamicznie) bibliotece, środowisko wykonawcze wysyła komunikat ładowania zaraz po załadowaniu biblioteki współużytkowanej do przestrzeni adresowej procesu.
Ponadto środowisko wykonawcze wysyła loaddo obiektu klasy tylko wtedy, gdy ten obiekt klasy sam implementuje loadmetodę. Przykład:
@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
Środowisko wykonawcze wysyła loadkomunikat do Superclassobiektu klasy. To nie nie wysyła loadwiadomość do Subclassobiektu klasy, choć Subclassdziedziczy metodę od Superclass.
Środowisko wykonawcze wysyła loadkomunikat do obiektu klasy po wysłaniu loadkomunikatu do wszystkich obiektów nadklasy klasy (jeśli te obiekty nadklasy są zaimplementowane load) i wszystkich obiektów klas w bibliotekach współdzielonych, do których tworzysz łącze. Ale nie wiesz jeszcze, które inne klasy w twoim własnym pliku wykonywalnym otrzymały load.
Każda klasa, którą twój proces ładuje do swojej przestrzeni adresowej, otrzyma loadkomunikat, jeśli implementuje loadmetodę, niezależnie od tego, czy twój proces używa tej klasy w inny sposób.
Można zobaczyć, jak środowisko wykonawcze wyszukuje loadmetodę jako szczególny przypadek w _class_getLoadMethodod objc-runtime-new.mm, i wzywa go bezpośrednio z call_class_loadsw objc-loadmethod.mm.
Środowisko uruchomieniowe uruchamia również loadmetodę każdej ładowanej kategorii, nawet jeśli kilka kategorii na tym samym implementacji klasy load. To jest niezwykłe. Zwykle, jeśli dwie kategorie definiują tę samą metodę w tej samej klasie, jedna z metod „wygra” i zostanie użyta, a druga nigdy nie zostanie wywołana.
initializeMetoda
Środowisko wykonawcze wywołuje initializemetodę na obiekcie klasy tuż przed wysłaniem pierwszej wiadomości (innej niż loadlub initialize) do obiektu klasy lub jakichkolwiek instancji klasy. Ta wiadomość jest wysyłana przy użyciu normalnego mechanizmu, więc jeśli twoja klasa nie implementuje initialize, ale dziedziczy po klasie, która to robi, wtedy twoja klasa użyje swojej nadklasy initialize. Środowisko wykonawcze wyśle najpierw initializedo wszystkich nadklas klasy (jeśli nadklasy nie zostały jeszcze wysłane initialize).
Przykład:
@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;
}
Ten program wypisuje dwa wiersze wyniku:
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
Ponieważ system wysyła initializemetodę leniwie, klasa nie otrzyma komunikatu, chyba że program faktycznie wyśle komunikaty do klasy (lub podklasy albo instancji klasy lub podklas). Zanim to zrobisz initialize, wszystkie zajęcia w Twoim procesie powinny już być load(jeśli to konieczne).
Kanoniczny sposób implementacji initializejest następujący:
@implementation Someclass
+ (void)initialize {
if (self == [Someclass class]) {
// do whatever
}
}
Celem tego wzorca jest uniknięcie Someclassponownej inicjalizacji, gdy ma podklasę, która nie jest implementowana initialize.
Środowisko wykonawcze wysyła initializekomunikat w _class_initializefunkcji w formacie objc-initialize.mm. Możesz zobaczyć, że używa objc_msgSenddo wysłania, co jest normalną funkcją wysyłania wiadomości.
Dalsza lektura
Zobacz piątkowe pytania i odpowiedzi Mike'a Asha na ten temat.
+loadjest wysyłany oddzielnie dla kategorii; oznacza to, że każda kategoria w klasie może zawierać własną+loadmetodę.