Ich bin daran interessiert, die Umstände zu verstehen, unter denen ein Entwickler + initialisieren oder + laden überschreibt. Die Dokumentation macht deutlich, dass diese Methoden von der Objective-C-Laufzeit für Sie aufgerufen werden, aber das ist wirklich alles, was aus der Dokumentation dieser Methoden hervorgeht. :-)
Meine Neugier kommt von Apples Beispielcode - MVCNetworking. Ihre Modellklasse hat eine +(void) applicationStartup
Methode. Es führt einige Verwaltungsarbeiten im Dateisystem durch, liest NSDefaults usw. usw. und nach dem Versuch, die Klassenmethoden von NSObject zu analysieren, scheint es in Ordnung zu sein, diese Hausmeisterarbeit in + load zu setzen.
Ich habe das MVCNetworking-Projekt geändert, den Aufruf in App Delegate an + applicationStartup entfernt und die Housekeeping-Bits in + load geladen ... mein Computer hat kein Feuer gefangen, aber das bedeutet nicht, dass es korrekt ist! Ich hoffe, ein Verständnis für alle Feinheiten, Fallstricke und Dingsbums einer benutzerdefinierten Setup-Methode zu erlangen, die Sie im Vergleich zu + Laden oder + Initialisieren aufrufen müssen.
Für + load Dokumentation heißt es:
Die Lademeldung wird an Klassen und Kategorien gesendet, die sowohl dynamisch geladen als auch statisch verknüpft sind, jedoch nur, wenn die neu geladene Klasse oder Kategorie eine Methode implementiert, die antworten kann.
Dieser Satz ist kludgey und schwer zu analysieren, wenn Sie nicht die genaue Bedeutung aller Wörter kennen. Hilfe!
Was ist mit "sowohl dynamisch geladen als auch statisch verknüpft" gemeint? Kann etwas dynamisch geladen UND statisch verknüpft werden oder schließen sie sich gegenseitig aus?
"... die neu geladene Klasse oder Kategorie implementiert eine Methode, die antworten kann" Welche Methode? Antworten wie?
In Bezug auf + initialize heißt es in der Dokumentation:
initialize wird nur einmal pro Klasse aufgerufen. Wenn Sie eine unabhängige Initialisierung für die Klasse und für Kategorien der Klasse durchführen möchten, sollten Sie Lademethoden implementieren.
Ich verstehe das so: "Wenn Sie versuchen, die Klasse einzurichten ... verwenden Sie nicht initialize." Okay gut. Wann oder warum sollte ich dann die Initialisierung überschreiben?
quelle
+load
für Kategorien separat gesendet wird. Das heißt, jede Kategorie in einer Klasse kann eine eigene+load
Methode enthalten.initialize
dies von einerload
Methode bei Bedarf korrekt aufgerufen wird , daload
auf die nicht initialisierte Entität verwiesen wird. Dies kann (seltsamerweise, aber vernünftig) dazu führen, dassinitialize
man vorher läuftload
! Das habe ich jedenfalls beobachtet. Dies scheint im Widerspruch zu "Und bis Sie erhalteninitialize
, sollte jede Klasse in Ihrem Prozess bereits erhalten habenload
(falls zutreffend)."load
zuerst. Sie können dann empfangen,initialize
währendload
noch läuft.Was es bedeutet, ist,
+initialize
in einer Kategorie nicht zu überschreiben , Sie werden wahrscheinlich etwas kaputt machen.+load
wird einmal pro Klasse oder Kategorie aufgerufen, die implementiert wird+load
, sobald diese Klasse oder Kategorie geladen wird. Wenn "statisch verknüpft" angezeigt wird, bedeutet dies, dass es in Ihre App-Binärdatei kompiliert wurde. Die+load
so kompilierten Methoden für Klassen werden beim Start Ihrer App ausgeführt, wahrscheinlich bevor sie eingegeben wirdmain()
. Wenn "dynamisch geladen" steht, bedeutet dies, dass es über Plugin-Bundles oder einen Aufruf von geladen wirddlopen()
. Wenn Sie mit iOS arbeiten, können Sie diesen Fall ignorieren.+initialize
wird aufgerufen, wenn eine Nachricht zum ersten Mal an die Klasse gesendet wird, kurz bevor sie diese Nachricht verarbeitet. Dies passiert (offensichtlich) nur einmal. Wenn Sie+initialize
in einer Kategorie überschreiben , geschieht eines von drei Dingen:Aus diesem Grund sollten Sie
+initialize
eine Kategorie niemals überschreiben. Tatsächlich ist es ziemlich gefährlich, eine Methode in einer Kategorie zu ersetzen, da Sie nie sicher sind, was Sie ersetzen oder ob Ihr eigener Ersatz selbst durch eine andere Kategorie ersetzt wird.Übrigens, ein weiteres Problem, das Sie berücksichtigen sollten,
+initialize
ist, dass Sie möglicherweise einmal für Ihre Klasse und einmal für jede Unterklasse aufgerufen werden, wenn jemand Sie unterordnet. Wenn Sie beispielsweisestatic
Variablen einrichten, sollten Sie sich davor schützen: entweder mitdispatch_once()
oder durch Testenself == [MyClass class]
.quelle