web-dev-qa-db-fra.com

iOS: sous-classe UIView init ou initWithFrame :?

J'ai créé une sous-classe de UIView qui a un cadre fixe. Alors, puis-je simplement remplacer init au lieu de initWithFrame:? Par exemple.:

- (id)init {
    if ((self = [super initWithFrame:[[UIScreen mainScreen] bounds]])) {
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

La documentation Xcode pour -initWithFrame: dit: "Si vous créez un objet de vue par programme, cette méthode est l'initialiseur désigné pour la classe UIView. Les sous-classes peuvent remplacer cette méthode pour effectuer une initialisation personnalisée mais doivent appeler super à la début de leur mise en œuvre. "

Que signifie "initialiseur désigné"?

37
ma11hew28

L'initialiseur désigné est celui que tous les autres initialiseurs doivent appeler. UIView et les sous-classes sont un peu inhabituelles car elles ont en fait deux de ces initialiseurs: -initWithFrame: et -initWithCoder:, selon la façon dont la vue est créée. Vous devez remplacer -initWithFrame: si vous instanciez la vue dans le code, et -initWithCoder: si vous le chargez depuis une plume. Ou, vous pouvez mettre votre code dans la troisième méthode et remplacer ces deux initialiseurs de sorte qu'ils appellent votre troisième méthode. En fait, c'est souvent la stratégie recommandée.

Ainsi, par exemple, vous pouvez créer une sous-classe UIView, ClueCharacter, qui a sa propre méthode d'initialisation: -initWithPerson:place:thing:. Vous créez ensuite votre vue comme ceci:

Obj-C:

ClueCharacter *mustard = [[ClueCharacter alloc] initWithPerson:@"Col. Mustard"
                                                         place:kInTheStudy
                                                         thing:kTheRope];

Rapide:

var mustard = ClueCharacter("Col. Mustard", place: kInTheStudy, thing: kTheRope)

C'est très bien, mais pour initialiser la partie UIView de l'objet, votre méthode must appelez l'initialiseur désigné:

Obj-C:

-(id)initWithPerson:(NSString*)name place:(CluePlace)place thing:(ClueWeapon)thing
{
    if ((self = [super initWithFrame:CGRectMake(0, 0, 150, 200)])) {
        // your init stuff here
    }
}

Rapide:

func init(name: String, place : CluePlace, thing : ClueWeapon)
{
    if (self = super.init(CGRectMake(0, 0, 150, 200))) {
       // your init stuff here
    }
}

Si vous souhaitez appeler l'initialiseur de votre sous-classe -init, ça va tant que vous appelez -initWithFrame: dans l'implémentation.

73
Caleb

dans UIView appelant [super init] est exactement égal à [super initWithFrame:CGRectZero]

23
user1411443

Dans une classe Objective-C avec plusieurs initialiseurs, l'initialiseur désigné est celui qui effectue le travail significatif. Donc, souvent vous avez une classe avec quelques initialiseurs, dites:

- (id)initWithRect:(CGRect)someRect;

- (id)initWithRect:(CGRect)someRect setDefaultColour:(BOOL)setDefaultColour;

- (id)initWithRect:(CGRect)someRect setDefaultColour:(BOOL)setDefaultColour
             linkTo:(id)someOtherObject;

Dans ce cas, vous diriez normalement (mais pas toujours) que le troisième est l'initialiseur désigné, et implémentez les deux autres comme par ex.

- (id)initWithRect:(CGRect)someRect
{
    return [self initWithRect:someRect setDefaultColour:NO];
}

- (id)initWithRect:(CGRect)someRect setDefaultColour:(BOOL)setDefaultColour
{
    return [self initWithRect:someRect setDefaultColour:setDefaultColour
                   linkTo:nil];
}

Si une classe n'a qu'un seul initialiseur, c'est l'initialiseur désigné.

Dans votre cas, pour suivre les meilleures pratiques, vous devez implémenter initWithFrame: et aussi une Vanille init: qui appelle initWithFrame: avec vos dimensions normales. La convention normale est que vous pouvez ajouter de nouvelles variations sur init dans les sous-classes, mais que vous ne devez pas en supprimer, et que vous effectuez toujours le travail d'initialisation réel dans l'initialiseur désigné. Cela permet à toutes les méthodes d'initialisation de la classe parente dont vous ne fournissez pas de nouvelles implémentations de fonctionner correctement avec votre sous-classe.

3
Tommy