web-dev-qa-db-fra.com

Les changements de cadre de vue entre viewWillAppear: et viewDidAppear:

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

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

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

et la sortie de journal résultante:

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. Je voulais faire la configuration avec la vue dans la méthode viewDidLoad, mais si le contenu ne peut pas être modifié tant qu'il n'est pas affiché à l'écran, cela semble plutôt inutile. Que pourrait-il se passer?

83
Jumhyn

Autolayout a considérablement modifié la manière dont nous concevons et développons l'interface graphique de nos vues. Une des principales différences est que autolayout ne change pas immédiatement la taille de nos vues, mais uniquement lorsque cela se produit, cela signifie à un moment précis, mais nous pouvons le forcer à recalculer immédiatement nos contraintes ou à les marquer comme " dans le besoin "de mise en page. Cela fonctionne comme -setNeedDisplay.
Le grand défi pour moi a été de comprendre et d’accepter le fait que nous n’avons plus besoin d’utiliser des masques à sélection automatique, et que le cadre est devenu une propriété inutile pour positionner nos vues. Nous n'avons plus besoin de penser à la position de la vue, mais nous devrions penser à la façon dont nous voulons les voir dans un espace lié les uns aux autres.
Lorsque nous souhaitons mélanger l’ancien masque de réaugmentation automatique et la suppression automatique, c’est lorsque des problèmes se posent. Nous devrions penser très tôt à la mise en œuvre de la mise en mémoire automatique et éviter de mélanger l'ancienne approche dans une hiérarchie de vues basée sur la mise en pause automatique.
Convient bien d'avoir une vue conteneur qui utilise uniquement des masques à redimensionnement automatique, telle qu'une vue principale d'un contrôleur de vue, mais cette méthode est préférable si vous n'essayez pas de mélanger.
Je n’ai jamais utilisé de scénarimage, mais très probablement, c’est correct. À l'aide de l'autolayout, les cadres de vos vues sont définis lorsque le moteur de l'autolayout commence son calcul. Essayez de demander la même chose juste après le super de la méthode - (void)viewDidLayoutSubviews de votre contrôleur de vue.
Cette méthode est appelée à la fin du calcul automatique des vues de votre moteur.

107
Andrea

De la documentation:

viewWillAppear:

Indique 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.

En conséquence, les cadres des sous-vues ne sont pas encore définis dans le viewWillAppear:

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

viewDidLayoutSubviews

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

153
George Sachpatzidis

appel

self.scrollView.layoutIfNeeded ()

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

7
andrei

Dans mon cas, déplacer toutes les méthodes liées aux images vers

override func viewWillLayoutSubviews()

a parfaitement fonctionné (j’essayais de modifier les contraintes du storyboard).

3