NSObject +charge +et initialiser - Que font-ils?
Je suis intéressé à comprendre les circonstances qui ont conduit à un développeur de remplacer +initialiser ou +de la charge. La Documentation précise de ces méthodes sont appelées par l'Objective-C de l'exécution, mais c'est vraiment tout ce qui est clair à partir de la documentation de ces méthodes. 🙂
Ma curiosité vient de regarder Apple exemple de code MVCNetworking. Leur modèle de classe a un +(void) applicationStartup
méthode. Il fait un peu de ménage sur le système de fichiers, lit NSDefaults, etc etc... et, après avoir essayé de grok NSObject de méthodes de la classe, il semble que ce nettoyage peut être bien de mettre en +de la charge.
J'ai fait modifier le MVCNetworking projet, la suppression de l'appel en Application Délégué à +applicationStartup, et de mettre de l'entretien ménager des bits dans +de charge... mon ordinateur n'a pas pris feu, mais cela ne veut pas dire que c'est correct! Je suis l'espoir de comprendre les subtilités, les pièges, et dressoirs autour d'une configuration personnalisée, la méthode que vous avez à les appeler, contre +charge ou +initialiser.
Pour les +de la charge de la documentation dit:
La charge message est envoyé à des classes et des catégories qui sont à la fois
chargé dynamiquement et statiquement, mais seulement si le nouveau chargé
de la classe ou de la catégorie met en œuvre une méthode qui peut répondre.
Cette phrase est kludgey et difficile d'analyser si vous ne connaissez pas la signification de tous les mots. À l'aide!
-
Qu'entend-on par "les deux chargés dynamiquement et statiquement?" Quelque chose peut être chargé dynamiquement ET statiquement, ou sont-elles incompatibles?
-
"...le nouveau chargé de classe ou de catégorie met en œuvre une méthode qui peut répondre" Quelle méthode? Réagir comment?
Comme pour +d'initialiser, de la documentation dit:
initialiser elle est invoquée qu'une seule fois par catégorie. Si vous souhaitez effectuer
indépendant de l'initialisation de la classe et pour les catégories de la
de la classe, vous devez mettre en œuvre la charge des méthodes.
Je prends ce à dire, "si vous essayez de configuration de la classe... n'utilisez pas l'initialiser." Bien, très bien. Quand ou pourquoi aurais-je remplacer initialiser alors?
Vous devez vous connecter pour publier un commentaire.
La
load
messageLe runtime envoie le
load
message à chaque objet de classe, très vite, après la classe de l'objet est chargé dans l'espace d'adressage du processus. Pour les classes qui font partie du fichier exécutable du programme, l'exécution envoie leload
message très tôt dans le processus de la vie. Pour les classes qui sont dans une commune (chargées dynamiquement) la bibliothèque, le moteur d'exécution envoie la charge message juste après la bibliothèque partagée est chargé dans l'espace d'adressage du processus.En outre, le moteur d'exécution n'envoie
load
à un objet de classe si la classe de l'objet lui-même met en œuvre laload
méthode. Exemple:Le runtime envoie le
load
message à laSuperclass
objet de classe. Il ne pas envoyer leload
message à laSubclass
objet de classe, même siSubclass
hérite de la méthode deSuperclass
.Le runtime envoie le
load
message à un objet de classe après qu'il a envoyé leload
message à l'ensemble de la classe de super-classe des objets (si ces super-classe des objets de mettre en œuvreload
) et tous les objets de la classe dans les bibliothèques partagées que vous liez. Mais vous ne savez pas qui d'autres classes dans votre propre fichier exécutable ont reçuload
encore.Chaque classe de votre processus de charge dans son espace d'adressage recevrez un
load
message, si elle met en œuvre laload
méthode, peu importe si votre processus rend toute autre utilisation de la classe.Vous pouvez voir comment le moteur d'exécution regarde le
load
méthode comme un cas particulier dans la_class_getLoadMethod
deobjc-runtime-nouvelle.mm
, et des appels directement à partir decall_class_loads
dansobjc-loadmethod.mm
.Le moteur d'exécution gère également le
load
méthode de chaque catégorie, il charge, même si plusieurs catégories sur la même classe en œuvreload
. Ce est inhabituel. Normalement, si les deux catégories de définir la même méthode dans la même catégorie, l'une des méthodes de “gagner” et être utilisé, et l'autre méthode ne sera jamais appelé.La
initialize
MéthodeL'exécution appelle la
initialize
méthode sur un objet de classe juste avant l'envoi du premier message (autres queload
ouinitialize
) à la classe de l'objet ou des instances de la classe. Ce message est envoyé en utilisant le mécanisme normal, donc, si votre classe n'implémente pasinitialize
, mais hérite d'une classe qui ne, alors votre classe va utiliser sa super-classeinitialize
. Le moteur d'exécution envoyer leinitialize
à l'ensemble de la classe des super-classes de première (si les super-classes n'ont pas déjà été envoyéinitialize
).Exemple:
Ce programme imprime deux lignes de sortie:
Depuis le système envoie le
initialize
méthode paresseusement, une classe ne recevez pas le message, à moins que votre programme envoie des messages à la classe (ou une sous-classe, ou des instances de la classe ou sous-classes). Et au moment où vous recevezinitialize
, chaque classe dans votre processus devrait déjà avoir reçuload
(le cas échéant).La manière canonique de mettre en œuvre
initialize
est-ce:Le point de ce modèle est à éviter
Someclass
ré-initialisation de lui-même lorsqu'il a une sous-classe qui n'est pas de mettre en œuvreinitialize
.Le runtime envoie le
initialize
message dans le_class_initialize
fonction dansobjc-initialiser.mm
. Vous pouvez voir qu'il utiliseobjc_msgSend
pour les envoyer, ce qui est la forme normale de l'envoi de messages de fonction.Lecture
Découvrez Mike Cendres du vendredi de Q&A sur ce sujet.
+load
est envoyé séparément pour les catégories, c'est, chaque catégorie sur une classe peut contenir son propre+load
méthode.initialize
sera correctement invoqué par unload
méthode, si nécessaire, à cause de laload
faisant référence à l'entité non initialisée. Cela peut (bizarrement, mais raisonnablement) conduisent àinitialize
en cours d'exécution avantload
! C'est ce que j'ai observé, de toute façon. Cela semble être contraire à la "Et au moment où vous recevezinitialize
, chaque classe dans votre processus devrait déjà avoir reçuload
(le cas échéant)."load
premier. Vous pouvez alors recevoirinitialize
toutload
est toujours en cours d'exécution.Ce que cela signifie, c'est de ne pas remplacer
+initialize
dans une catégorie, vous aurez probablement casser quelque chose.+load
est appelée une fois par classe ou d'une catégorie qui implémente+load
, dès que de la classe ou de la catégorie est chargé. Quand il dit "statiquement" cela signifie compilé dans votre application binaires. Le+load
méthodes sur les classes ainsi recueillies ne sera exécuté que lorsque votre application est lancée, probablement avant qu'il ne pénètremain()
. Quand il dit "chargé dynamiquement", cela signifie chargés via le plugin faisceaux ou un appel àdlopen()
. Si vous êtes sur iOS, vous pouvez ignorer cette affaire.+initialize
est appelé la première fois, un message est envoyé à la classe, juste avant qu'il ne gère que les message. C'est (évidemment) n'arrive qu'une fois. Si vous remplacez+initialize
dans une catégorie, l'une des trois choses peuvent se produire:C'est pourquoi vous ne devriez jamais ignorer
+initialize
dans une catégorie, en fait, il est très dangereux d'essayer et de le remplacer tout méthode dans une catégorie parce que vous n'êtes jamais sûr de ce que vous êtes en remplacement ou si votre propre remplacement sera lui-même mis à l'écart par une autre catégorie.BTW, une autre question à examiner avec
+initialize
est que si quelqu'un les sous-classes, vous serez potentiellement appelé une fois pour votre classe et une fois pour chaque sous-classe. Si vous êtes en train de faire quelque chose comme la mise en placestatic
variables, vous aurez envie de se prémunir contre cela: soit avecdispatch_once()
ou par des essaisself == [MyClass class]
.