2010-12-05 3 views
36

En Objective-C, est-il nécessaire de surcharger tous les constructeurs hérités d'une sous-classe pour ajouter une logique d'initialisation personnalisée?Surcharge init dans la sous-classe

Par exemple, est-ce que ce qui suit serait correct pour une sous-classe UIView avec une logique d'initialisation personnalisée?

@implementation CustomUIView 

- (id)init { 
    self = [super init]; 
    if (self) { 
     [self initHelper]; 
    } 
    return self; 
} 

- (id)initWithFrame:(CGRect)theFrame { 
    self = [super initWithFrame:theFrame]; 
    if (self) { 
     [self initHelper]; 
    } 
    return self; 
} 

- (id)initWithCoder:(NSCoder *)decoder { 
    self = [super initWithCoder:decoder]; 
    if (self) { 
     [self initHelper]; 
    } 
    return self; 
} 

- (void) initHelper { 
    // Custom initialization 
} 

@end 

Répondre

38

Chaque classe Cocoa Touch (et Cocoa) a un initialiseur désigné; pour UIView, comme indiqué in this documentation, cette méthode est initWithFrame:. Dans ce cas particulier, vous devrez uniquement remplacer initWithFrame; tous les autres appels tomberont en cascade et atteindront cette méthode, éventuellement.

Cela va au-delà de la portée de la question, mais si vous ne finissent par créer un initialiseur personnalisé avec des paramètres supplémentaires, vous devez vous assurer de l'initialiseur désigné pour la superclasse lors de l'attribution self, comme ceci:

- (id)initWithFrame:(CGRect)theFrame puzzle:(Puzzle *)thePuzzle title:(NSString *)theTitle { 
    self = [super initWithFrame:theFrame]; 
    if (self) { 
     [self setPuzzle:thePuzzle]; 
     [self setTitle:theTitle]; 
     [self initHelper]; 
    } 
    return self; 
} 
+1

Donc, même si je CustomUIView exemple init simple, il appellera initWithFrame? – hpique

+0

C'est correct. La façon de tester cela serait de remplacer à la fois init: et initWithFrame :, définir les points d'arrêt (ou les instructions NSLog) sur la première ligne de chaque, et l'instance CustomUIView en utilisant init. Vous devriez voir init get hit, suivi de initWithFrame :. –

+29

Ce qu'il est important de se rappeler est que si un objet est instancié à partir d'un NIB, 'initWithCoder:' est appelé, et ** NOT ** 'initWithFrame:'. – Pascal

4

En général, vous devez suivre la convention d'initialisation désignée. L'initialiseur désigné est init, qui couvre l'initialisation de toutes les variables d'instance. L'initialiseur désigné est également la méthode appelée par d'autres méthodes init d'une classe.

Apple documentation sur les initialiseurs désignés.

initWithFrame: est l'initialiseur désigné de la classe NSView. La documentation Cocoa d'Apple mentionne toujours explicitement l'initialisateur désigné d'une classe. Est discutée here on SO.

2

En cas d'utilisation Interface Builder, l'un est appelé est:

- (id)initWithCoder:(NSCoder *)coder 
{ 
    self = [super initWithCoder:coder]; 
    if (self) { 
     //do sth 
    } 
    return self; 
}