50 votes

Quand dois-je initialiser un contrôleur de vue en utilisant initWithNibName ?

Quand dois-je utiliser init: et quand dois-je utiliser initWithNibName:bundle: lors de la création d'un contrôleur de vue ?

0 votes

Vous devez modifier la réponse sélectionnée pour cette question

143voto

Rob Napier Points 92148

-initWithNibName:bundle: est l'initialisateur désigné pour UIViewController. Quelque chose devrait éventuellement l'appeler. Cela dit, et malgré les exemples d'Apple (qui privilégient la brièveté à la facilité de maintenance dans de nombreux cas), il ne doit jamais être appelé en dehors du contrôleur de vue lui-même.

Vous verrez souvent un code comme celui-ci :

MYViewController *vc = [[MYViewController alloc] initWithNibName:@"Myview" bundle:nil];

Je dis que c'est incorrect. Les détails de l'implémentation (le nom de la NIB et le fait qu'une NIB soit utilisée) sont confiés à l'appelant. Cela brise l'encapsulation. La façon correcte de procéder est la suivante :

MYViewController *vc = [[MYViewController alloc] init];

Ensuite, dans MYViewController :

- (instancetype)init
{
   self = [super initWithNibName:@"Myview" bundle:nil];
   if (self != nil)
   {
       // Further initialization if needed
   }
   return self;
}

- (instancetype)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle
{
    NSAssert(NO, @"Initialize with -init");
    return nil;
}

Cela permet de replacer les détails clés de l'implémentation dans l'objet, et empêche les appelants de briser accidentellement l'encapsulation. Maintenant, si vous changez le nom du NIB, ou si vous passez à la construction programmatique, vous le corrigez à un seul endroit (dans le contrôleur de vue) plutôt qu'à chaque endroit où le contrôleur de vue est utilisé.

3 votes

Si c'est la méthode prévue, pourquoi XCode4 génère-t-il un stub initWithNibName:bundle : pour chaque classe ViewController vide, mais pas de méthode init ?

2 votes

Pour la même raison que les modèles n'ont pas inclus les préfixes de classe, même si vous êtes censé préfixer vos classes, et le modèle crée le nom le plus stupide possible pour votre délégué d'application, ce qui est un vrai casse-tête à corriger. Et IB force une déclaration d'ivar lorsque vous créez automatiquement des propriétés, même si vous ne devriez pas déclarer d'ivars dans la nouvelle ABI. Les modèles ne sont pas toujours les meilleures pratiques. Ils sont souvent le plus petit dénominateur commun qui fonctionne un peu dans la plupart des cas, mais nulle part particulièrement bien. Le code d'exemple d'Apple s'est amélioré récemment, mais il a encore du chemin à parcourir.

1 votes

Si vous suivez la convention de nommer vos nibs de la même manière que la classe, ce code fonctionne bien : - (id)init { return [super initWithNibName:NSStringFromClass([self class]) bundle:nil]; }

9voto

bpapa Points 10188

Utilisez initWithNibName: bundle: si vous êtes... en train d'initialiser avec un fichier nib ! C'est-à-dire un fichier que vous avez créé avec Interface Builder.

Si vous n'utilisez pas IB pour mettre en page vos vues, vous pouvez simplement utiliser init .

2voto

Kiet Nguyen Points 101

Vous pouvez simplement appeler init, tant que le xib a le même nom que la classe du contrôleur de vue. L'encapsulation n'est pas nécessaire. Cela permet d'économiser de la frappe, mais peut ne pas servir la clarté.

 NUDMainViewController *mainVC = [[NUDMainViewController alloc] init];

1voto

JosephT Points 117

Utiliser init lorsqu'il n'y a pas de fichier nib/xib, par exemple lorsque les IU sont créées par codage

en utilisant initWithNibName, si nous avons un nib/xib ou un même contrôleur partagé par plus d'un nib/xib.

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
     self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil];
 } else {
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil];
 }

C'est ce que je pense

0 votes

Vous savez que si vous ajoutez ~iphone ou ~ipad à vos noms de nib, vous pouvez simplement appeler initWithNibName@"ViewController" et il choisira le bon.

-4voto

Charybdis Points 577

Si vous prévoyez de créer votre vue avec Interface Builder, vous utiliserez initWithNibName:bundle :. La fonction init est utilisée si vous avez l'intention de configurer la hiérarchie de votre vue dans le code.

Beaucoup de gens n'utilisent Interface Builder que pour construire des applications, ce qui permet de faire le travail, mais je vous recommande d'apprendre à tout faire en code. IB automatise beaucoup de choses et le résultat final n'est pas toujours exactement ce que vous voulez, mais si vous configurez tout en code, vous avez beaucoup plus de contrôle. J'ai très peu utilisé Interface Builder, et je suis content d'avoir pris le temps d'apprendre à tout faire en code. Si vous êtes vraiment pressé par le temps, IB peut être le moyen le plus rapide, mais à long terme, la programmation manuelle des vues en vaut la peine.

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