web-dev-qa-db-fra.com

viewWillAppear, viewDidAppear n'étant pas appelé, ne se déclenchant pas

(Il s'agit à la fois d'une question et d'une réponse, car il a fallu beaucoup de temps pour trouver la vraie réponse.)

Symptôme: viewWillAppear, viewDidAppear n'étaient pas appelés dans mon UIViewController.

Cause: l'incorporation d'un UINavigationController ou UITabBarController (mon cas) dans un UIViewController interrompt en quelque sorte l'appel de ces méthodes.

Solution: appelez-les manuellement dans le UIViewController qui contient le UINavigationController/UITabBarController susmentionné.

Par exemple (en supposant que projectNavigationController est votre UINavigationController):

vide) viewWillAppear: (BOOL) animé {
 [super viewWillAppear: animé]; 
 [projectNavigationController viewWillAppear: animé]; 
} 
 
 - (vide) viewWillDisappear: (BOOL) animée {
 [super viewWillDisappear: animated]; 
 [projectNavigationController viewWillDisappear: animated]; 
} 
 
 - (vide) viewDidAppear: (BOOL) animé {
 [super viewDidAppear: animé]; 
 [projectNavigationController viewDidAppear: animé]; 
} 
 
 - (vide) viewDidDisappear: (BOOL) animé {
 [super viewDidDisappear: animated]; 
 [projectNavigationController viewDidDisappear: animated]; 
} 

Dans mon cas, j'avais un UITabBarController intérieur et j'ai appelé les méthodes en conséquence et tout a été résolu.

(Attribution de la solution: --- (http://davidebenini.it/2009/01/03/viewwillappear-not-being-called-inside-a-uinavigationcontroller/ )

38
pschang

Je vais aller de l'avant et être en désaccord avec @ St3fan, et utiliser UIKit comme contre-exemple.

Cependant, la sagesse (ou le manque de sagesse) de l'intégration des contrôleurs en général devrait être guidée par des principes de conception sains de l'interface utilisateur.

Le contre-exemple le plus simple est UINavigationControllers incorporé dans UITabBarControllers. Ceux-ci apparaissent partout. Juste en haut de ma tête, l'application iPod sur iPhone et les contacts dans l'application Téléphone sur iPhone.

J'étais assez curieux pour prendre la peine de vérifier ce qu'ils font avec les vues (ajouter à la vue "super-contrôleur" ou à la UIWindow. J'étais presque sûr que j'allais trouver que les vues du sous-contrôleur étaient descendants des vues du super-contrôleur dans la hiérarchie des vues, ce qui est contraire à la recommandation de St3fan.

J'ai créé une application iPhone très rapide qui connecte tout dans InterfaceBuilder pour créer une application basée sur UITabBarController avec deux onglets, dont le premier était un UINavigationController avec un simple ole UIViewController comme c'est le contrôleur de vue racine, et un deuxième onglet avec un vieux UIViewController simplement pour que j'aie un deuxième onglet à cliquer plus tard.

Saupoudrez quelques instructions NSLog pour afficher les divers UIView's pour les contrôleurs, nous voyons ceci:

tabBarController.view = <UILayoutContainerView: 0x5b0dc80; ...
navigationController.view = <UILayoutContainerView: 0x59469a0; ...
rootViewController.view = <UIView: 0x594bb70; ...
Superview: <UIViewControllerWrapperView: 0x594cc90; ...
Superview: <UINavigationTransitionView: 0x594a420; ...
Superview: <UILayoutContainerView: 0x59469a0; ... // navigationController.view
Superview: <UIViewControllerWrapperView: 0x594b430; ...
Superview: <UITransitionView: 0x5b0e110; ...
Superview: <UILayoutContainerView: 0x5b0dc80; ... // tabBarController.view
Superview: <UIWindow: 0x5942a30; ...

Les lignes préfixées par "Superview" étaient le résultat de la remontée du rootViewController.view's chaîne superview jusqu'à ce qu'elle atteigne zéro.

Ensuite, bien sûr, un coup d'œil rapide sur la pile d'appels à quelques endroits où viewDidDisappear serait appelé sur le contrôleur de vue racine.

Tout d'abord, la pile d'appels lorsque viewDidDisappear est appelée sur le contrôleur racine à la suite d'un nouveau contrôleur poussé sur la pile:

-[RootController viewDidDisappear:]
-[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:]
...

Deuxièmement, la pile d'appels lorsqu'un autre onglet est sélectionné dans le UITabBarController le plus haut:

-[RootController viewDidDisappear:]
-[UINavigationController viewDidDisappear:]
-[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:]

Donc, dans tous les cas, il semble que Apple a décidé que les contrôleurs devraient appeler les diverses méthodes viewDidAppear, etc. sur leurs sous-contrôleurs intégrés et que les vues devraient être intégrées de la même manière. Je pense que l'OP a frappé ce clou juste sur la tête si nous devons prendre UIKit design comme une bonne piste à suivre.

10
imaginaryboy

Je viens de voir cette même circonstance. Plus tôt, la séquence de création d'interface déclenchée par une sélection de cellule de tableau avait cessé de fonctionner et après une exaspération à creuser dans le code, je l'ai simplement configuré manuellement, en appelant à partir de la substitution de sélection de cellule dans le délégué de vue de table.

Plus tard, j'ai fait quelques changements de disposition dans le contrôleur de vue appelé et j'ai vu que viewDidAppear n'était pas appelé, comme décrit ci-dessus. La sortie de débogage faisait référence à des "opérations Push imbriquées" ou quelque chose comme ça, et puisque j'avais un gros commentaire à me faire dans mon opération Push manuelle

#warning I SHOULD NOT HAVE TO DO THIS!!

J'ai pointé le code de séquence et, bien sûr, la séquence IB fonctionnait maintenant, et c'était mon opération manuelle dans le code de sélection des cellules du tableau qui gâchait les appels des délégués dans la vue appelée. J'ai supprimé le code manuel et tout va bien à nouveau.

Il semble étrange que le code de sélection de cellule soit appelé après avoir poussé la vue. Je dois faire un protocole et déléguer pour obtenir le chemin d'index de la cellule sélectionnée dans l'appelant.

0
Chris Fox