Comment fonctionne View Controller Containment dans iOS 5?

108

Dans la WWDC 2011 Session 102, Apple a introduit View Controller confinement, qui est la capacité de créer des conteneurs de contrôleur d'affichage personnalisé, analogue à UITabBarController, UINavigationControlleret autres.

J'ai regardé les exemples plusieurs fois. Il existe une multitude de méthodes associées à ce modèle, mais il était un peu difficile de les comprendre exactement. Je vais poster ici ce que je pense qui se passe et voir si la communauté va confirmer ou infirmer mes soupçons.

Scénario 1: passer de l'absence de parent à un nouveau contrôleur de vue parent

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

Les deux premières lignes doivent-elles apparaître dans l'ordre indiqué ou peuvent-elles être inversées?

Scénario 2: passer d'un contrôleur de vue parent à aucun contrôleur de vue parent

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

Est-il également nécessaire d'appeler [vc didMoveToParentViewController:nil]? Les exemples de la session 102 n'ont pas fait cela dans ce scénario, mais je ne sais pas si c'était une omission ou non.

Scénario 3: passage d'un contrôleur de vue parent à un autre

Cela se produira probablement de la manière suivante, car la logique de chaque contrôleur de vue parent sera encapsulée.

// In the old parent
[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

// In the new parent
[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];

Des questions

Ma question principale est la suivante: est-ce ainsi que le confinement du contrôleur de vue devrait fonctionner, en général? Les mécanismes donnés ci-dessus sont-ils corrects?

Est-il nécessaire d'appeler willMoveToParentViewControlleravant d'appeler addChildViewController? Cela me semble être l'ordre logique, mais est-ce strictement nécessaire?

Est-il nécessaire d'appeler didMoveToParentViewController:nilaprès avoir appelé removeFromParentViewController?

Gregory Higley
la source

Réponses:

72

Les UIViewControllerdocuments sont assez clairs sur quand et quand ne pas appeler willMove/ didMovemethods. Consultez la section «Implémentation d'un contrôleur de vue de conteneur» .

Les documents disent que si vous ne remplacez pas addChildViewController, vous n'avez pas à appeler la willMoveToParentViewController:méthode. Cependant, vous devez appeler la didMoveToParentViewController:méthode une fois la transition terminée. "De même, il est de la responsabilité du contrôleur de vue du conteneur d'appeler la willMoveToParentViewController:méthode avant d'appeler la removeFromParentViewControllerméthode. La removeFromParentViewControllerméthode appelle ledidMoveToParentViewController: méthode du contrôleur de vue enfant."

En outre, il existe un exemple élaboré ici et un exemple de code ici .

Bonne chance

timthetoolman
la source
17
Je vois, donc addChildViewControllerdevrait être équilibré avec didMoveToParentViewControlleret willMoveToParentViewControllerdevrait être équilibré avec removeFromParentViewController. Ceci est exactement ce que je cherchais. Je ne sais pas comment je l'ai manqué dans la documentation.
Gregory Higley
Pourquoi pas? Pourquoi vous n'avez pas besoin d'appeler willMoveToParentViewController mais devez-vous appeler didMoveToParentViewController?
user4951
Parce que c'est ce que disent les documents. Apple pense évidemment que nous n'avons pas besoin de savoir.
7
La raison est pour l'animation: disons que vous créez votre propre contrôleur de navigation. Au début d'une animation slide-in, 'willMove' doit être appelé, et à la fin de l'animation, 'didMove' doit être appelé. Maintenant, lorsque vous appelez «addChild» au début de l'animation, il appelle automatiquement «willMove» pour vous. Mais il ne peut pas savoir quand l'animation (s'il y en a une) se termine, vous devez donc appeler 'didMove' manuellement à la fin de l'animation (ou immédiatement sur aucune animation).
Chris
2
Et comme pour une animation 'slide out', par exemple l'enfant est en cours de suppression, vous devez appeler 'willMove' manuellement au début de l'animation, car autrement uikit ne saurait pas quand appeler 'viewWillDisappear' de votre VC enfant. Et à la fin de l'animation, lorsque vous appelez removeFromParentViewController, il peut appeler «didMove» automatiquement pour vous.
Chris
23

Cette partie n'est pas correcte:

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

Selon la documentation:

Lorsque votre conteneur personnalisé appelle la méthode addChildViewController :, il appelle automatiquement la méthode willMoveToParentViewController: du contrôleur de vue à ajouter en tant qu'enfant avant de l'ajouter.

Vous n'avez donc pas besoin de l' [vc willMoveToParentViewController:self]appel. Cela se fait automatiquement lorsque vous appelez [self addChildViewController:vc]. Voici à nouveau l'exemple de code:

[self addChildViewController:vc];
// [vc willMoveToParentViewController:self] called automatically
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

Pour supprimer des contrôleurs de vue:

La méthode removeFromParentViewController appelle automatiquement la méthode didMoveToParentViewController: du contrôleur de vue enfant après avoir supprimé l'enfant.

Vraisemblablement, cet appel est [oldVC didMoveToParentViewController:nil].

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
// [vc didMoveToParentViewController:nil] called automatically
roi nevan
la source
il semble que si cela est fait autrement, même si cela semble fonctionner, PresentViewController n'est pas défini sur le presentViewController.
Adrian
Les documents disent appeler didMoveToParentViewController " immédiatement après avoir appelé la méthode addChildViewController:", cela ne spécifie pas quand vous ajoutez réellement la sous-vue enfant. Je me demande si tout le monde s'est trompé. Y a-t-il un exemple dans certains documents Apple sur lesquels nous pouvons vérifier cela?
Robert le
Note: vous avez besoin d'appeler willMoveToParentViewControlleravant addChildViewControllersi l'élément que vous déplacez est une classe personnalisée avec surchargée addChildViewController(sauf si votre override appelle en interne)
bunkerdive