113 votes

NSObject + charger et + initialize - 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?

183voto

rob mayoff Points 124153

L' load message

Le moteur d'exécution envoie l' load message pour chaque classe d'objet, 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 l' load 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 d'une classe d'objet si la classe de l'objet lui-même met en œuvre l' load méthode. Exemple:

@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

Le moteur d'exécution envoie l' load message à l' Superclass de la classe d'objet. Il ne pas envoyer l' load message à l' Subclass de la classe d'objet, même si Subclass hérite de la méthode de Superclass.

Le moteur d'exécution envoie l' load message à un objet de classe après qu'il a envoyé l' load message à l'ensemble de la classe de super-classe des objets (si ces super-classe des objets de mettre en oeuvre load) et de 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çu load encore.

Chaque classe de votre processus de charge dans son espace d'adressage recevrez un load message, si elle implémente l' load méthode, peu importe si votre processus rend toute autre utilisation de la classe.

Vous pouvez voir comment le runtime recherche l' load méthode comme un cas particulier dans l' _class_getLoadMethod de objc-runtime-new.mm, et des appels directement à partir de call_class_loads en objc-loadmethod.mm.

Le moteur d'exécution gère également l' load méthode de chaque catégorie, il charge, même si plusieurs catégories sur la même classe d'implémenter load. C'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é.

L' initialize Méthode

Le moteur d'exécution envoie l' initialize méthode à un objet de classe juste avant l'envoi du premier message (autres que load ou initialize) à 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'est pas mise en œuvre d' initialize, mais hérite d'une classe qui ne, alors votre classe va utiliser sa super-classe initialize. Le moteur d'exécution d'envoyer l' initialize de l'ensemble de super-classes d'une classe de première (si les super-classes n'ont pas déjà été envoyé initialize).

Exemple:

@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;
}

Ce programme imprime deux lignes de sortie:

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

Depuis que le système envoie l' 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 recevez initialize, chaque classe dans votre processus devrait déjà avoir reçu load (le cas échéant).

La manière canonique pour mettre en oeuvre initialize est-ce:

@implementation Someclass

+ (void)initialize {
    if (self == [Someclass class]) {
        // do whatever
    }
}

Le point de ce modèle est à éviter Someclass re-initialisation de lui-même lorsqu'il a une sous-classe qui n'est pas mise en œuvre d' initialize.

Le moteur d'exécution envoie l' initialize message dans l' _class_initialize fonction objc-initialize.mm. Vous pouvez voir qu'il utilise objc_msgSend pour les envoyer, ce qui est la forme normale de l'envoi de messages de fonction.

Lectures complémentaires

Découvrez Mike Cendres du vendredi de Q&A sur ce sujet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X