J'ai une UIViewController
que je charge depuis un autre contrôleur de vue, puis en ajoutant sa vue à une UIScrollView
.
self.statisticsController = [self.storyboard instantiateViewControllerWithIdentifier:@"StatisticsViewController"];
self.statisticsController.match = self.match;
[self.scrollView addSubview:self.statisticsController.view];
J'ai mis des points d'arrêt dans le contrôleur d'affichage des statistiques et viewDidLoad
est appelé, mais viewWillAppear
ne l'est pas.
Est-ce parce que je ne le pousse pas sur la hiérarchie ou quelque chose?
Vous devez ajouter statisticsController
en tant que contrôleur de vue enfant du contrôleur auquel vous ajoutez la vue.
self.statisticsController = [self.storyboard instantiateViewControllerWithIdentifier:@"StatisticsViewController"];
self.statisticsController.match = self.match;
[self.scrollView addSubview:self.statisticsController.view];
[self addChildViewController:self.statisticsController];
[self.statisticsController didMoveToParentViewController:self];
Je ne suis pas sûr que cela va faire appeler viewDidAppear
, mais vous pouvez remplacer didMoveToParentViewController:
dans le contrôleur enfant, ce qui sera appelé, de sorte que vous pouvez insérer le code que vous auriez mis dans viewDidAppear
.
Je rencontre à nouveau le problème -viewWillAppear:
non appelé. Après avoir googlé, je suis venu ici. J'ai fait quelques tests et découvert que l'ordre d'appel de -addSubview
et -addChildViewController:
est important.
Cas 1. déclenchera -viewWillAppear:
du contrôleur, mais Cas 2, it WON'T call -viewWillAppear:
.
Cas 1:
controller?.willMoveToParentViewController(self)
// Call addSubview first
self.scrollView.addSubview(controller!.view)
self.addChildViewController(controller!)
controller!.didMoveToParentViewController(self)
Cas 2:
controller?.willMoveToParentViewController(self)
// Call adChildViewController first
self.addChildViewController(controller!)
self.scrollView.addSubview(controller!.view)
controller!.didMoveToParentViewController(self)
Par défaut, les rappels d'apparence sont automatiquement transférés aux enfants . Ils sont déterminés à l'aide de la propriété shouldAutomaticallyForwardAppearanceMethods. Vérifiez la valeur de cette propriété, s'il s'agit de NO et si votre viewController enfant doit apparaître directement sur l'apparence du conteneur, vous devez avertir l'enfant avec les méthodes suivantes dans l'implémentation du cycle de vie du contrôleur du conteneur:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
for (UIViewController *child in self.childViewControllers) {
[child beginAppearanceTransition:YES animated:animated];
}
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.child endAppearanceTransition];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
for (UIViewController *child in self.childViewControllers) {
[child beginAppearanceTransition:NO animated:animated];
}
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.child endAppearanceTransition];
}
Personnalisation du comportement des rappels d'apparence et de rotation
Correction de mon problème! J'espère que ce serait utile.
Comme indiqué dans une autre réponse, le contrôleur de vue parent peut ne pas appeler viewWillAppear
etc. lorsque shouldAutomaticallyForwardAppearanceMethods
est défini sur false
. UINavigationController
et UITabBarController
sont connus pour le faire. Dans ce cas, vous devez appeler beginAppearanceTransition(_ isAppearing: Bool, animated: Bool)
sur le contrôleur de vue enfant avec isAppearing
défini sur true
lorsque la vue apparaît et inversement.
Vous devez placer ces appels aux endroits appropriés dans votre code, normalement lorsque vous ajoutez et supprimez votre contrôleur de vue enfant.
N'oubliez pas d'appeler endAppearanceTransition
sur votre contrôleur de vue enfant lorsque votre transition personnalisée est terminée. Sinon, viewDidAppear
et viewDidDisappear
ne sont pas appelés.
Selon Apple ( https://developer.Apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html ), l'ordre correct des appels d'API pour ajouter un contrôleur de vue enfant est le suivant:
[self addChildViewController:childVC];
[self.view addSubview:childVC.view];
[childVC didMoveToParentViewController:self];
Mais j'avais toujours le problème où viewWillAppear chez l'enfant VC n'était pas appelé sporadiquement. Mon problème était qu'il y avait une condition de concurrence critique qui pouvait entraîner l'exécution du code ci-dessus avant que viewDidAppear dans le contrôleur de vue du conteneur ne soit appelé. S'assurer que viewDidAppear avait déjà été appelé (ou différer l'ajout de l'enfant VC jusqu'à ce qu'il le soit) l'a résolu pour moi.
Les réponses précédentes sont correctes, mais si cela peut aider quelqu'un - si vous écrasez loadView
dans le contrôleur de vue enfant, aucune autre méthode UIViewController n'est appelée.
Il m’a fallu un peu de temps pour comprendre pourquoi mon code ne fonctionnait pas correctement, jusqu’à ce que j’ai réalisé que j’avais accidentellement remplacé loadView
au lieu de viewDidLoad
.
Dans mon cas, j'ai trouvé que réécrivait à tort une méthode viewWillAppear:
dans ma classe UINavigationController
de base:
override func viewWillAppear(_ animated: Bool) {
super.viewWillDisappear(animated)
// other stuff
}
Notez qu'au lieu d'appeler super.viewWillAppear(animated)
, j'ai écrit super.viewWillDisappear(animated)
.
Cela a causé que tous les UIViewController
s qui étaient dans cette UINavigationController
n'appelaient pas la méthode viewWillAppear:
.
Espérons que cela aide quelqu'un sur un problème similaire.