2017-03-15 4 views
0

La substitution initialize() est courante pour l'exécution du code avant qu'une classe ne reçoive son premier message (réglage UserDefaults, etc.). La documentation indique qu'une mise en œuvre de superclasse peut être appelée sous-classes multiples fois ne sont pas prioritaires initialize() et donnent un exemple d'un moyen de protéger une classe de l'exécution du code plus d'une fois si initialize() est appelée à plusieurs reprises:Redéfinition de l'initialisation sur un AppDelegate - Protection contre l'exécution répétée du code

Le l'implémentation de la superclasse peut être appelée plusieurs fois si les sous-classes n'implémentent pas initialize() - l'exécution appelle l'implémentation héritée - ou si les sous-classes appellent explicitement [super initialize]. Si vous voulez vous protéger d'être plusieurs fois exécuter, vous pouvez structurer votre mise en œuvre le long de ces lignes:

+ (void)initialize { 
    if (self == [ClassName self]) { 
    // ... do the initialization ... 
    } 
} 

Je PRÉPONDÉRANTS initialize() dans mon AppDelegate et en essayant d'éviter le code avoir couru plus d'une fois. Le contrôle de classe n'a pas de sens pour moi, en vérifiant si self is AppDelegate.Type va toujours évaluer à vrai (et me donne un avertissement dans Xcode).

Est-ce que la vérification de la classe ne s'applique pas, puisque nous ne sommes pas dans une superclasse (la superclasse de AppDelegate est UIResponder)? Est-ce que le contenu de ma méthode initialize() surchargée ne s'exécutera qu'une seule fois sans appeler super ou effectuer une vérification de classe?

+0

Je pense que si vous utilisez '===' au lieu de 'is', cela ne retournera pas true pour les sous-classes de' AppDelegate'. – dan

+0

@dan Hmm, je n'ai pas envisagé de comparer les références. C'est aussi une bonne option, et protège contre les sous-classes. Vous devriez publier cela comme une réponse. – JAL

+0

Ou 'if self == AppDelegate.self'. Mais tant que vous ne sous-classez pas AppDelegate, vous n'avez pas besoin de cette vérification. –

Répondre

0

La raison de la vérification de la classe est que vous ne souhaitez généralement exécuter le code sur initialize qu'une seule fois (conformément aux documents). L'écriture de cette condition vous protège des sous-classes qui n'implémentent pas initialize ou n'appellent pas le [super initialize]. Voici une hiérarchie de classe par exemple:

class Animal: NSObject { 
    class func initialize() { 
     //Some code I only want to run once 
    } 
} 


class Dog: Animal {} 

Quand j'instancier une nouvelle Dog, le moteur d'exécution Objective-C sera envoyé à la méthode initialize-toutes les classes dans la hiérarchie de Dog (superclasses en premier), de sorte que Dog recevra la message, mais il en sera de même pour Animal. Parce que Dog n'implémente pas initialize, sa super-classe recevra le message, donc si vous n'ajoutez pas la vérification qui s'assure que le message était destiné à cette classe, votre code finira par s'exécuter deux fois.

Ce doesn't really make sense in Swift, et probablement encore moins dans un AppDelegate donc si vous voulez avoir le code exécuté qu'une seule fois à Swift, vous devriez probablement utiliser paresseusement initialisées ou GLOBALS propriétés statiques, telles que définies dans the migration docs.