87 votes

Le cadre de la vue change entre viewWillAppear : et viewDidAppear :

J'ai découvert un comportement étrange dans mon application. IBOutlet a son cadre de vue connecté entre les appels de mon contrôleur de vue à viewWillAppear: y viewDidAppear: . Voici le code correspondant dans mon UIViewController sous-classe :

-(void)viewWillAppear:(BOOL)animated {
    NSLog(@"%@", self.scrollView);
}

-(void)viewDidAppear:(BOOL)animated {
    NSLog(@"%@", self.scrollView);
}

et la sortie du journal qui en résulte :

MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 0; 0 0); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}>
MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 44; 320 416); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}>

Ce qui montre clairement que le cadre change entre les deux appels. J'ai voulu faire une configuration avec la vue dans le fichier viewDidLoad mais si je ne peux pas modifier le contenu tant qu'il n'est pas à l'écran, cela semble assez inutile. Que se passe-t-il ?

157voto

George Sach Points 2112

Desde el la documentation :

viewWillAppear:

Notifie au contrôleur de vue que sa vue est sur le point d'être ajoutée à une hiérarchie de vues.

viewDidAppear:

Notifie au contrôleur de vue que sa vue a été ajoutée à une hiérarchie de vues.

Par conséquent, les cadres des vues secondaires ne sont pas encore définis dans le fichier viewWillAppear :

La méthode appropriée pour modifier l'interface utilisateur avant que la vue ne soit présentée à l'écran est :

viewDidLayoutSubviews

Notifie au contrôleur de vue que sa vue vient de déployer ses sous-vues.

112voto

Andrea Points 6580

Autolayout a apporté un changement considérable dans la manière dont nous concevons et développons l'interface graphique de nos vues. L'une des principales différences est que autolayout ne modifie pas la taille des vues immédiatement, mais seulement lorsqu'il est déclenché, c'est-à-dire à un moment précis, mais nous pouvons le forcer à recalculer nos contraintes immédiatement ou à les marquer comme "nécessitant" une mise en page. Cela fonctionne comme suit -setNeedDisplay .
Le grand défi pour moi a été de comprendre et d'accepter que nous n'avons plus besoin d'utiliser les masques d'autoréglage, et que le cadre est devenu une propriété inutile pour placer nos vues. Nous n'avons plus besoin de penser à la position des vues, mais nous devons penser à la façon dont nous voulons les voir dans un espace lié les uns aux autres.
C'est lorsque l'on veut mélanger l'ancien masque de redimensionnement et l'autolayout que les problèmes surgissent. Nous devrions réfléchir à l'implémentation de l'autolayout très rapidement et essayer d'éviter de mélanger l'ancienne approche dans une hiérarchie de vues basée sur l'autolayout.
Il est possible d'avoir une vue conteneurisée qui n'utilise que des masques de redimensionnement automatique, comme la vue principale d'un contrôleur de vue, mais il est préférable de ne pas essayer de mélanger les deux.
Je n'ai jamais utilisé de storyboard, mais c'est probablement correct. En utilisant Autolayout, les cadres de vos vues sont définis lorsque le moteur Autolayout commence ses calculs. Essayez de poser la même question juste après la superposition de - (void)viewDidLayoutSubviews de votre contrôleur de vue.
Cette méthode est appelée lorsque le moteur autolayout a fini de calculer les cadres de vos vues.

9voto

andrei Points 839

Appel

self.scrollView.layoutIfNeeded()

dans votre viewWillAppear méthode. Ensuite, vous pouvez accéder à son cadre et il aura la même valeur que celle que vous avez imprimée dans la méthode viewDidAppear

4voto

Dans mon cas, j'ai déplacé toutes les méthodes liées au cadre dans le module

override func viewWillLayoutSubviews()

a parfaitement fonctionné (j'essayais de modifier les contraintes à partir du storyboard).

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