Résumé : Comment le UIViewController doit-il connaître la taille de son instance UIView lors de l'initialisation de cette vue ?
La méthode d'initialisation dédiée à une UIView est la méthode initWithFrame :(CGRect)frame. Elle définit le cadre de la UIView nouvellement créée. Cette méthode peut être appelée à partir de la méthode loadView du UIViewController, si la vue de ce contrôleur d'affichage est demandée. La documentation de UIViewController indique ce qu'il faut faire en ce qui concerne le sous-classement et la taille de la vue :
Lorsque vous créez les vues de votre hiérarchie de vues vous devez toujours définir l'option propriétés de redimensionnement de vos vues. Lorsqu'un contrôleur de vues est affiché à l'écran l'écran, sa vue racine est généralement redimensionnée pour s'adapter à l'espace disponible, qui peut varier en fonction de l'orientation l'orientation actuelle de la fenêtre et de la présence d'autres éléments d'interface tels que la barre d'état.
Ainsi, l'instance UIViewController doit définir ces propriétés. Jusqu'ici tout va bien, le UIViewController n'a pas besoin de connaître la taille de sa vue.
Lorsque la vue d'un UIViewController est demandée et que la propriété view est nulle, la méthode loadView du contrôleur de vue est appelée. Il y a maintenant un problème, car l'UIView doit être initialisée, mais le contrôleur de vue ne sait toujours pas quelle doit être la taille de la vue. Quelle taille doit-on initialiser cette vue ? Où dans le code déterminez-vous la taille de la vue ?
Vous pourriez initialiser la vue avec un rectangle zéro (CGRectZero) :
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
}
Et laissez l'appelant définir le cadre de vue comme suit :
UIViewController *viewController = [[MyUIViewController alloc] init];
// next two lines are normally combined, but for clarity they are not now
UIView *view = viewController.view;
view.frame = CGRectMake(0, 0, 200, 200);
Celui-ci demande la vue au contrôleur de vue (viewController.view), et charge donc sa vue avec la méthode loadView. Cette méthode loadView initialise la vue avec un CGRectZero. Ensuite, l'appelant définit son cadre (view.frame = ...).
Le problème est que la propriété frame de la vue est définie deux fois, ce qui peut entraîner un double travail supplémentaire si votre UIView personnalisée effectue une mise en page avancée dans la méthode setFrame (placement et redimensionnement des sous-vues, par exemple). Vous pouvez éviter cela en créant une méthode d'initialisation dédiée pour le UIViewController qui demande déjà à l'appelant un CGRect, que vous stockez dans un ivar. Au moment où la méthode loadView est appelée, vous utilisez cet ivar pour créer la vue.
Quelle est la bonne façon de procéder ici ? Soit en définissant deux fois le cadre de la vue (en l'initialisant avec CGRectZero, et en le définissant ensuite), soit en donnant au UIViewController une nouvelle méthode d'initialisation avec un CGRect (et donc en lui donnant une propriété de cadre) ? Ou bien est-ce que je rate quelque chose et y a-t-il d'autres possibilités ?