Lorsque vous utilisez des vues et des contrôleurs de vue dans une application iPhone, quelqu'un peut-il expliquer la différence entre loadView et viewDidLoad?
Mon contexte personnel, c’est que je construis toutes mes vues à partir de code, je n’utilise pas et n’utilisera pas Interface Builder, si cela pouvait changer quelque chose.
J'ai souvent constaté que lorsque j'ajoutais du code init à loadView, je me retrouvais avec une trace de pile infinie. Je construisais donc généralement toute la construction de la vue de l'enfant dans viewDidLoad ... quel est l'endroit le plus approprié pour mettre le code init. Ce qui serait parfait, est un simple diagramme des appels d’initialisation.
Merci!
Je peux deviner quel pourrait être le problème ici, car je l'ai fait:
J'ai constaté que souvent, lorsque j'ajoute du code init à loadView, je me retrouve avec une trace de pile infinie
Ne lisez pas self.view dans -loadView. Seulement définissez , ne le faites pas obtenir le.
L'accesseur de la propriété self.view appelle -loadView si la vue n'est pas chargée. Il y a votre récursion infinie.
La manière habituelle de créer la vue par programme dans -loadView, comme indiqué dans les exemples antérieurs d'Apple Interface-Builder, ressemble plus à ceci:
UIView *view = [[UIView alloc] init...];
...
[view addSubview:whatever];
[view addSubview:whatever2];
...
self.view = view;
[view release];
Et je ne vous en veux pas de ne pas utiliser IB. Je suis fidèle à cette méthode pour l'ensemble d'Instapaper et je me trouve beaucoup plus à l'aise que de gérer les complexités d'IB, les bizarreries d'interface et les comportements inattendus dans les coulisses.
loadView
est la méthode dans UIViewController
qui chargera la vue et l'attribuera à la propriété view
. C'est également l'emplacement qu'une sous-classe de UIViewController
écraserait si vous vouliez configurer par programme la propriété view
.
viewDidLoad
est la méthode appelée une fois la vue chargée. Ceci est appelé après que loadView soit appelé. C’est un endroit où vous pouvez remplacer et insérer du code qui permet d’établir plus avant la configuration initiale de la vue une fois celle-ci chargée.
viewDidLoad()
doit être utilisé lorsque vous chargez votre vue à partir d'une carte NIB et souhaitez effectuer toute personnalisation après son lancement
LoadView()
doit être utilisé lorsque vous souhaitez créer votre vue par programme (sans utiliser Interface Builder)
Ajoutez juste quelques exemples de code pour démontrer ce que NilObject a dit:
- (void)loadView
{
// create and configure the table view
myTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStyleGrouped];
myTableView.delegate = self;
myTableView.dataSource = self;
myTableView.scrollEnabled = NO;
self.view = myTableView;
self.view.autoresizesSubviews = YES;
}
- (void)viewDidLoad
{
self.title = @"Create group";
// Right menu bar button is to Save
UIBarButtonItem *saveButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleDone target:self action:@selector(save)];
self.navigationItem.rightBarButtonItem = saveButtonItem;
[saveButtonItem release];
}
Pour éviter qu'une boucle infinie ne se produise lorsque vous lisez self.view, appelez la super-implémentation de la classe lorsque vous chargez une vue. La super implémentation allouera une nouvelle UIView pour vous.
- (void) loadView {
[super loadview];
// init code here...
[self.view addSubView:mySubview1]; //etc..
}
loadView()
est appelé lorsque votre contrôleur est invité à créer son self.view
. Vous pouvez le faire vous-même comme
self.view = [UIView alloc] init...];
Ou bien la classe UIController parente de votre contrôleur a déjà un nom de méthode -loadView()
qui initialise votre self.view en vue vierge. Ensuite, vous pouvez appeler
[super loadView];
Je recommande vraiment la deuxième approche car elle encourage l'héritage. Seulement si votre contrôleur de vue n'est pas directement hérité de UIViewController.
Le moyen le plus simple d'utiliser loadView est de créer un type de contrôleur de vue de base, tel que MyBaseViewController, qui est la sous-classe de UIViewController. Dans sa méthode loadView, créez la vue de cette manière:
-(void) loadView {
if ([self viewFromNib]) {
self.view = [self viewFromNib];
} else {
self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
}
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
self.view.backgroundColor = [UIColor whiteColor];
}
Et lorsque vous avez besoin de créer un contrôleur de vue, vous utilisez simplement la sous-classe de MyBaseViewController et dans son contrôleur loadView, vous appelez simplement [super loadView] comme ceci:
//sucblass loadView
-(void) loadView {
[super loadView];
//rest of code like this..
UILabel *myLabel = [[UILabel alloc] initWithFrame:myFrame];
[self.view addSubview:myLabel];
[myLabel release];
}
La définition donnée par Apple sur viewDidLoad a indiqué qu’elle est appelée après que la vue du contrôleur a été chargée en mémoire. Pour le dire simplement, c’est la première méthode qui sera chargée.
Vous pensez peut-être dans quelles conditions cette méthode sera-t-elle pleinement utilisée? La réponse est, essentiellement, tout ce que vous vouliez que l'application charge en premier. Par exemple, vous pouvez choisir une couleur de fond différente, au lieu de blanc, vous pouvez choisir le bleu.