Autolayout + UIViewController + Rotation
Salut,
Je suis dans le dur avec Autolayout en ce moment. ::)
J'ai un VC, qui contient une vue partielle.
Celle vue ajoute soit:
- la tableView d'un autre VC
- la vue d'un UIPageViewController
Je n'ai aucun soucis avec la tableView: quand je fais une rotation du device, tout s'étire ou se rétrécit et tout colle aux bords.
Le problème est pour le PageViewController: la vue n'est pas adaptée après rotation (ou même à certains lancements), elle garde sa dimension d'origine, il faut la recharger pour que ça marche. Je ne pense pas que ce comportement soit normal.
Structure:
Dans mon VC d'origine:
self.pagesViewController.view.frame = self.dataView.bounds;
[self.dataView addSubview:self.pagesViewController.view];
Dans pagesViewController (hérite de VC et a un outlet vers UIPageViewController *pageViewController):
// manage the pageViewController
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
Dans pageViewController, rien de spécial, je définis les contraintes des sous-vues dans IB: ces contraintes sont bien prises en compte, le problème est en amont.
Réponses
Sinon je t'invite à utiliser le nouveau mode de Xcode6 pour déboguer les interfaces (vue éclatée / 3D) avec affichage des contraintes)
C'est la question que je me suis posée.
Pour la tableView, les contraintes sont dans le VC associé (dans IB).
Tu as des contraintes entre les vues de ton VC parent.
Tu as des contraintes à l'intérieur de ta vue qui contient ta UITableView.
Mais je ne vois pas où tu as mis des contraintes entre ta self.dataView et ton self.pageViewController.view.
C'est bien beau de faire un [self.dataView addSubview:self.pageViewController.view] mais quand tu fais ça il faut peut-être ajouter des contraintes ensuite entre l'un et l'autre, pour que la taille du self.pageViewController.view suive en permanence la taille de la self.dataView !
Je te dis, utilises le nouveau débugueur d'UI d'Xcode6 tu vas comprendre.
SI j'ai compris ta question et j'y ai même répondu.
Je ne vois pas, comment donner les contraintes entre la vue de pagesViewController et sa superview dataView, dans IB du moins... Faut-il passer par le code obligatoirement ?
J'ai utilisé la fonction view debug de Xcode 6 (mais ça ne m'a rien appris car je sais que la sous-vue rouge ne prend pas la taille de la superview bleue, j'utilise les couleurs quand j'ai des bugs de cet accabit). Par contre, je me suis payé 2 Kernel Panic grâce à cette feature de Xcode !
Et de toute façon quand tu enlève une UIView de sa superview, les contraintes qu'il y avait entre ces vues sont supprimées au passage (et encore heureux, car si après tu décidais d'ajouter cette UIView en subview à une autre superview qui n'a rien à voir avec la première, faudrait pas qu'il essaye de satisfaire des contraintes avec la première !!). Donc quand tu rajoutes une UIView en subview à une autre il faut aussi créer les contraintes qui vont avec.
Oups, ah ouais quand même ! Le genre de truc que j'ai pas vu depuis des lustres sur OSX ! BugReport d'urgence !
Tu as du coup de ce que je comprends 3 niveaux de UIViewController (et non pas 2 comme je l'avais compris de premier abord) :
1. Un UIViewController parent
2. Un UIViewController enfant, contenant un IBOutlet vers un UIPageViewController
3. Cet UIPageViewController donc.
Sauf que entre 1 et 2 tu ne fais qu'un ajout de subview sans faire un ajout de childViewController. Alors qu'entre 2 et 3 tu fais bien cet ajout de childViewController en + de l'ajout de subview... Pourquoi cette inconsistance / asymétrisme dans ton code ? Et du coup, ça veut dire si tu as 2 niveaux qu'il te manque les contraintes à la fois entre 1 et 2 et entre 2 et 3, non ?
Je crois que c'est exactement ça. J'ai essayé d'être précis dans mon premier post.
1. J'ai un VC qui a une dataView partielle (qui peut intégrer plein de vues de différents types).
2. Cette dataView ajoute la vue du VC "enfant" (pagesViewController) (je n'ai pas besoin d'ajouter de contraintes ici normalement) :
3. Dans le VC enfant, j'ai un outlet vers un pageViewController qui gère des VC enfants.
Il y aurait bien en effet 2 niveaux de contraintes, ce qui fait que je suis un peu perdu, entre 1 et 2 et entre 2 et 3. Reste à savoir où bien les mettre dans la hiérarchie.
Et sinon, décompose le problème à chaque niveau.
- Quand 1 ajoute le VC enfant 2 en subview, c'est lui qui ajoute des contraintes entre 1 et 2 (dans la foulée du addSubview).
- Quand 2 ajoute son UIPageViewController 3 en fils avec un addSubview, c'est lui qui ajoute les contraintes. Quoique pour lui, si ce VinoPagesViewController est défini à l'aide d'un XIB, il y a là sans doute moyen d'ajouter les contraintes via IB entre la UIView à la racine du XIB (la vue du VinoPagesViewController / File's Owner) et la UIView de ton UIPageViewController que tu as mis dedans.
Au final la relation 2-3 n'a rien d'exceptionnelle, c'est du classique dans IB. Si j'ai bien compris dans ton XIB tu as une UIView qui contient la vue du UIPageViewController et tu mets des contraintes dessus. Donc dans ce cas, pas besoin de code là dessus si pour le [2 addSubview:3] ni pour ajouter une contrainte entre 2 et 3, tu peux tout faire dans IB comme tu fais d'habitude.
Par contre, la relation 1-2 elle est dynamique (ton dataView contient une subview qui va différer selon les cas, pour afficher tantôt une UITableView et tantôt ton pagesViewController) et donc pour elle là tu vas forcément faire les [1 addSubview:2] par code (car tu dois certainement avoir une condition pour ajouter tantôt la tableview, tantôt le pagesVC j'imagine). Et là puisque tu fais le addSubview par code, il faut que tu fasses les contraintes entre 1 et 2 par code aussi.
Il y avait une raison, j'utilisais dans la V1 un autre système que UIPageViewController dans lequel j'avais besoin de ce niveau intermédiaire.
Donc, je viens de le supprimer et pagesViewController hérite directement de UIPageViewController.
Du coup, effectivement, je n'ai plus aucun problème d'autolayout et je dois ne rajouter aucun code !
Par contre, je perds le comportement du UIPageViewController: on ne peut plus naviguer.
Je dois délocaliser les méthodes de UIPageViewController datasource/delegate de VC2 vers VC1. C'est sûrement pour cette raison que j'avais gardé ce niveau intermédiaire: avoir tout ce qui se rapportait au UIPageViewController isolé dans VC2, au lieu de surcharger VC1.
Bon, j'ai réussi à garder mon niveau intermédiaire VC 2 (pour je le rappelle y exposer les méthodes delegate et datasource du UIPageViewController à la place de VC1).
Par contre, j'ai créé le UIPageViewController par le code:
à la place de l'outlet dans le XIB.
Au final, j'ai:
- un VC isolé (pour ne pas être dérangé) qui gère les pages
- l'autolayout qui marche enfin sans code supplémentaire !
Il reste que je ne comprends pas pourquoi l'outlet sur le UIPageViewController "foirait tout". Sûrement un mystère dans le XIB.