Quelle est la différence entre -viewWillAppear: et -viewDidAppear :?

131

Quelle est la différence entre -[UIViewController viewWillAppear:]et -[UIViewController viewDidAppear:]?

PJR
la source
1
merci BoltClock, mais donnez-moi un exemple des deux si possible ..
PJR
3
@BoltClock ce serait bien si c'était vrai. Je suppose que les 15 personnes qui ont voté pour ont lu le nom de la méthode mais ne l'ont jamais vraiment mesuré ... Je suis venu ici de Google parce que ce n'est PAS la différence entre eux
Adam
1
Plus précisément: parentView.viewDidAppear est appelé LONGTEMPS avant qu'Apple n'affiche réellement parentView ... Apple peint d'abord (de manière atomique) toutes les sous-vues ... et si vous avez beaucoup de sous-vues, ou complexes, alors "viewDidAppear" peut être appelé des dizaines ou des centaines de millisecondes trop tôt :(.
Adam

Réponses:

292

En général, voici ce que je fais:

1) ViewDidLoad - Chaque fois que j'ajoute des contrôles à une vue qui devrait apparaître avec la vue, tout de suite, je les mets dans la méthode ViewDidLoad. Fondamentalement, cette méthode est appelée chaque fois que la vue a été chargée en mémoire. Ainsi, par exemple, si ma vue est un formulaire avec 3 étiquettes, j'ajouterais les étiquettes ici; la vue n'existera jamais sans ces formes.

2) ViewWillAppear : J'utilise ViewWillAppear généralement juste pour mettre à jour les données sur le formulaire. Donc, pour l'exemple ci-dessus, je l'utiliserais pour charger réellement les données de mon domaine dans le formulaire. La création d'UIViews est assez coûteuse, et vous devriez éviter autant que possible de le faire avec la méthode ViewWillAppear, car lorsque cela est appelé, cela signifie que l'iPhone est déjà prêt à montrer l'UIView à l'utilisateur, et tout ce que vous faites ici aura un impact sur les performances de manière très visible (comme les animations retardées, etc.).

3) ViewDidAppear : Enfin, j'utilise ViewDidAppear pour démarrer de nouveaux threads sur des choses qui prendraient beaucoup de temps à exécuter, comme par exemple faire un appel de service Web pour obtenir des données supplémentaires pour le formulaire ci-dessus. existe déjà et est affiché à l'utilisateur, vous pouvez montrer un joli message «En attente» à l'utilisateur pendant que vous obtenez les données.

Chetan Bhalara
la source
4
Désolé, mais que voulez-vous dire par "charger les données de mon domaine dans le formulaire" dans viewWillAppear? Vous voulez dire télécharger via le réseau? Mais vous suggérez également de télécharger des éléments viewDidAppear?
Philip007
1
@ Philip007 Je pense que Stack fait référence à ce type de domaine: en.wikipedia.org/wiki/Domain-specific_modeling . Les données sont chargées à partir de vos modèles ou similaires.
dentarg
2
Cette réponse devrait être dans la documentation. Cela a été vraiment utile pour clarifier la différence entre les trois méthodes. Je vous remercie!
GangstaGraham
1
+1 J'avais un peu de confusion pour comprendre la différence entre ces trois, mais vous venez de l'éclaircir plus que parfaitement @ChetanBhalara
Chisx
@ChetanBhalara mais si vous travaillez longtemps, ViewDidAppearvous risquez facilement de confondre l'utilisateur avec l'interface utilisateur :)
hqt
46

viewDidLoad === >>> Mettez votre code d'initialisation ici. Ne placez pas de données dynamiques susceptibles de changer au cours du cycle de vie de la vue. Donc, si vous extrayez des données à partir de données de base, vous ne voulez pas le faire ici si cela pourrait changer pendant la durée de vie de la vue. Par exemple: disons que vous avez un contrôleur d'onglets. Vous passez de tab1 à tab2 et changez quelque chose sur le modèle dans tab2. Si vous revenez à tab1 et que le code de votre modèle a été créé dans viewDidLoad, cela ne sera pas mis à jour (en supposant que vous n'utilisez pas KVO ou NSFetchedResultsController, etc.).

viewWillAppear === >>> Ceci est appelé chaque fois que la vue est sur le point d'apparaître, que la vue soit déjà en mémoire ou non. Placez votre code dynamique ici, comme la logique du modèle.

viewDidAppear === >>> Placez ici les opérations coûteuses que vous ne voulez faire que si vous êtes sûr que la vue est à l'écran, comme les appels réseau.

Remarque: si votre application est en arrière-plan et revient au premier plan, vous devez gérer cela à l'aide de NSNotificationCenter. J'ai écrit le code pour cela dans les commentaires ci-dessous. Vous pourriez penser que viewWillAppear / viewDidAppear se déclenchera. Mettez-y un point de rupture et testez-le. Il ne tire pas. Donc, si quelque chose a changé pour votre application alors qu'elle était en arrière-plan, vous devrez le mettre à jour à l'aide de notifications.

smileBot
la source
1
ViewWill ou ViewDid sont-ils exécutés chaque fois que vous annulez la réduction de l'application?
Jeef
2
@Jeef C'est une excellente question. Ni l'un ni l'autre ne sont exécutés à moins que l'application ne soit tuée par le système ou par l'utilisateur en arrière-plan. Ce que vous devez faire pour être averti lorsque l'application n'est pas minimisée, c'est que vous devez utiliser NSNotificationCenter et addObserver pour le nom UIApplicationWillEnterForegroundNotification. Le sélecteur doit être applicationWillEnterForeground: il a un paramètre NSNotification. Mettez votre code dans cette méthode pour recharger les données, etc. Ce que vous pouvez faire est de créer une méthode de rechargement que vous appelez de cette méthode et également viewDidAppear si elles doivent être identiques.
smileBot
2
@Jeef quelque chose comme ceci: - (void) viewDidLoad {[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector (applicationWillEnterForeground :) nom: UIApplicationWillEnterForegroundNotification object: nil]; } - (void) applicationWillEnterForeground: (NSNotification *) notif {// répondez ici avec n'importe quoi}
smileBot
12

La viewWillAppearméthode est appelée avant de charger la vue réelle.

La viewDidAppearméthode est appelée lorsque la vue est déjà chargée et que vous souhaitez afficher quelque chose.

puneet kathuria
la source
9

viewWillAppear:
■ Appelé avant que la vue ne soit ajoutée à la hiérarchie de vues des fenêtres
■ Appelé avant [vc.view layoutSubviews] (si nécessaire)
viewDidAppear :
■ Appelé après l'ajout de la vue à la hiérarchie de vues
■ Appelé après [vc.view layoutSubviews] (si nécessaire)

Andyqee
la source
7

Quelques observations:

  • La viewDidLoadméthode est appelée lors de la première instanciation de la vue. IBOutletles références sont connectées au moment où cela a été appelé, mais pas avant. L' frameestime ne peut être établie au moment où cela a été appelé, cependant. C'est un excellent endroit pour ajouter / configurer des sous-vues et leurs contraintes associées. Mais si vous effectuez une configuration manuelle des framevaleurs sur la base des dimensions de la vue principale, la configuration de ces cadres doit être différée jusqu'à viewWillAppearou viewDidLayoutSubviews.

  • La viewWillAppearméthode est appelée lorsque la présentation de la vue dans la hiérarchie des vues est sur le point de commencer. Notamment, cela est appelé au début de l'animation (le cas échéant) de la présentation de la vue. Son compagnon, viewWillDisappearest évidemment appelé lorsque la transition loin de cette vue commence.

  • La viewDidAppearméthode est appelée lorsque la présentation de la vue est terminée, notamment lorsque toute animation associée est terminée. Son compagnon, viewDidDisappearest évidemment appelé lorsque la transition hors de cette vue est effectuée.

Deux mises en garde importantes:

  • viewDidLoadest appelée une et une seule fois, lorsque la vue est instanciée pour la première fois. D'autre part, viewWillAppearet viewDidAppearsera appelé non seulement lorsque la vue est présentée pour la première fois, mais à chaque fois que la même vue en question est re-présentée. Par exemple, lorsque vous présentez une vue pour la première fois, ces trois méthodes seront appelées. Si la vue en question présente par la suite une autre vue qui est ensuite rejetée, le viewWillAppearet viewDidAppearsera généralement rappelé lorsque la vue en question est ajoutée et animée à nouveau dans la hiérarchie de vues, mais viewDidLoadne le sera pas. viewDidLoadn'est appelée que lorsque cette instance particulière est créée pour la première fois.

    Donc, si vous voulez faire quelque chose à chaque fois qu'une vue réapparaît (par exemple, vous la fermez ou y revenez), faites-le dans viewWillAppearou viewDidAppear. Si vous souhaitez que cela se produise uniquement lorsque la vue est instanciée pour la première fois, faites-le dans viewDidLoad.

  • L'appel de viewWillAppearne garantit pas que la transition vers cette vue sera jamais achevée. Notamment, si vous utilisez une transition interactive pilotée par une entrée utilisateur en temps réel, mais que cette transition interactive peut être annulée. C'est-à-dire, juste parce que viewWillAppearc'est appelé, cela ne signifie pas que viewDidAppearsera appelé. C'est généralement le cas, mais si le geste interactif est annulé, ce ne sera pas le cas (car la transition n'est jamais terminée).

    Lors de la WWDC 2013, dans le contexte des transitions interactives, un présentateur a plaisanté en disant qu'ils devraient renommer viewWillAppear" viewMightAppear, ou viewWillProbablyAppear, ou iReallyWishThisViewWouldAppear".

    Un exemple de geste interactif intégré est lorsque vous utilisez un UINavigationControlleret que vous «faites glisser votre doigt depuis le bord gauche» pour lancer un pop de la vue. Le viewWillAppearsera appelé pour la vue dans laquelle vous faites apparaître, mais si vous annulez ce "balayage depuis le bord gauche" pour revenir à la vue à partir de laquelle vous avez commencé ce geste pop, le pop est annulé et le viewDidAppearpour la vue que vous avez commencé à pop back to ne sera jamais appelé.

    L'effet net de ceci est que vous devez faire attention à ne pas écrire de code qui suppose que chaque appel à viewWillAppearsera éventuellement suivi d'un appel à viewDidAppear. Si la transition est annulée, ce ne sera pas le cas.

Rob
la source
5

viewwillappear appellera avant de charger la vue afin que vous puissiez effectuer certaines tâches avant de charger cette vue et viewdidappear appellera après le chargement de la vue afin que la tâche de publication soit effectuée dans cette méthode

dks1725
la source
4

Différence entre "will" et "did" ... Comme son nom l'indique, viewWillAppear est appelé avant que la vue ne soit sur le point d'apparaître et viewDidAppear est appelé lorsque la vue est apparue.

Mahesh
la source
regardez la réponse acceptée bro, qui contient plus de 70 votes positifs. :)
PJR
4

1) ViewWillAppear : La vue chargée réellement dans la mémoire, appelée une fois dans le contrôleur de vue et avait son cadre, mais n'apparaissait toujours pas à l'utilisateur

2) ViewDidAppear : Le contrôleur ajouté à la hiérarchie de la vue, vous pouvez donc présenter au contrôleur suivant, également, la vue a mis en page les sous-vues

Abuzeid Ibrahim
la source
3

Le premier se produit avant l'apparition de la vue et le second se produit après.

Marc Abramowitz
la source
3

Pour résumer:

-viewWillAppear -> mettre à jour les données (recharger les données à partir d'une vue de table)

-viewDidAppear -> opérations coûteuses (appel API avec une belle progression!)

Nahuel Roldan
la source
1

Comme son nom l'indique, viewWillAppearest appelé avant l'apparition de la vue et viewDidAppearest appelé lorsque la vue est apparue.

visakh7
la source
0

Cas d'utilisation , c'est- à- dire quand dois-je utiliser lequel?

viewDidLoad - lorsque des étiquettes, des boutons (i, e tous les contrôles / sous-vues) sont connectés au fichier d'interface de la vue et si vous souhaitez les charger en même temps que la vue de ViewController, et si vous voulez charger ceci en mémoire une fois et être fait avec

viewWillAppear- par exemple, vous voulez changer la couleur d'arrière-plan de la vue à chaque fois que viewController apparaît à l'écran. Ou de manière plus réaliste si vous voulez une couleur d'arrière-plan DarkMode la nuit du jour et une couleur claire de la vue d'arrière-plan pendant la journée, optez pour ce code dansviewWillAppear

Un autre bon cas d'utilisation ici https://stackoverflow.com/a/39395865/5438240

Notez également que, si vous utilisez une pile de navigation ( UINavigationController), le viewController qui est sur le point d'être ouvert a viewWillDisappear()appelé, et le ViewController qui sera ensuite au-dessus de la pile aura viewWillAppear()appelé

Naishta
la source