Conseils archi pour créer un custom UIViewNavigationController
Bonjour à tous !
Ce post est hyper long, je l'ai un peu écrit comme si je discutais avec un mec qui s'y connaà®t bien et qui pouvait m'aider ! L'écrire m'a aidé à y voir plus clair. Si vous avez des réponses à me donner, ou si ce post peut lancer une discussion... ce serait cool
Je me lance dans une partie "archi" pour mon app et comme ce sont des questions très nouvelles pour moi, je poste pour avoir vos idées et vos conseils !
1. Préambule
Pourquoi ces questions sont nouvelles pour moi ?
- childVC et parentVC : je n'ai jamais utilisé
- content VC : je n'ai jamais utilisé
- en gros, je suis un OSX-ien en voie de conversion à iOS
- je n'ai encore jamais utilisé le SDK iOS7.0
- remarque : je n'utilise pas storyboard
2. Ce que je veux faire
Je souhaiterais créer un méchanisme pour gérer les push/pop entre vues. En gros, imaginez une frame dans l'écran et dans cette frame, on peut pusher (de gauche à droite, de haut en bas) d'une vue à une autre.
- un view controller (un content view controller ?)
Je pense que UINavigationController ne correspond exactement à ce que je veux car :
- j'aimerais pouvoir customiser mes animations push
- je ne veux pas de barre navigation (j'ai ma propre barre de navigation)
- à terme j'aimerais pouvoir rendre l'animation pop interactive via ma barre de navigation
- en fait peut être que UINavigationController est bon pour moi (remarque : je n'ai JAMAIS utilisé UINavigationController)...
3. Ce que je compte faire (qu'en pensez-vous, critiques ?)
- créer une classe MyCustomNavigationController, avec des méthodes pour push, poper, customiser les transitions, éventuellement interagir avec la transition
- cette classe a un lien strong vers un UIViewControllerTransitioningDelegate
- voire cette classe a un lien strong vers un UIViewControllerInteractiveTransitioning
- cette classe n'affiche qu'un seul childVC
- cette classe garde en mémoire les type de transitions qui ont été utilisées (droite->gauche, haut->bas, etc.) pour bien gérer les pop
- en gros, c'est une classe un peu vide, qui se contente de gérer les objets qui s'occupent des transitions
Du coup, une classe importante est MyCustomTransitionManager. C'est là dedans que je vais metter mes animations.
5. Le problème des tailles
Un problème que je vois arriver, c'est que j'aimerais que les childVC s'adaptent en taille à mon CustomNavigationController...
Je vois 2 solutions :
a) un méchanisme automatique qui ajoute des contraintes. En gros, j'ajoute childVC.view à customNavigationVC.view et j'ajoute des contrainte pour forcer la hauteur et la largeur.
MAIS, j'ai peur que quand l'animation du push se fasse, les contraintes ne soient bien à jour... Est-ce ce que je délire et non, les contraintes vont bien se mettre à jour vite ? J'ai aussi peur des conflits de contraintes.
a') peut-être permettre via l'interface d'ajouter ou non ces contraintes
b ) autre solution, très différente. Je me débrouille pour connaà®tre la taille de customNavigationVC.view (cette taille dépend d'autres contraintes). Et, dans mes childVC, quand je les instancie, je passe en paramètre cette taille.
Est-ce que c'est débile de vouloir procéder comme ça ? (genre : pourquoi ne pas utiliser auto layout... ?)
4. Mes interfaces.
Qu'en pensez-vous ?
#import <UIKit/UIKit.h>
@class MyCustomTransitionManager ;
@interface MyCustomNavigationController : UIViewController
typedef NS_ENUM(NSInteger, MyCustomNavigationControllerTransition)
{
MyCustomNavigationControllerTransitionNoTransition = 0,
MyCustomNavigationControllerTransitionSlideTowardsBottom,
MyCustomNavigationControllerTransitionSlideTowardsRight,
MyCustomNavigationControllerTransitionSlideTowardsTop,
MyCustomNavigationControllerTransitionSlideTowardsLeft,
MyCustomNavigationControllerTransitionError
};
#pragma mark - Init
- (instancetype)initWithFrame:(CGRect)frame ;
#pragma mark - Object state
@property (nonatomic, readonly) NSUInteger indexCurrentChildViewController ;
#pragma mark - Transition
@property (nonatomic, assign, readwrite) MyCustomNavigationControllerTransition nextTransitionType ;
@property (nonatomic, assign, readonly) MyCustomTransitionManager * navigationManager ;
// éventuellement un objet pour gérer l'interactivité (swipe pour le pop)
#pragma mark - Core methods
- (void)pushViewController:(UIViewController *)viewController ;
- (void)pushViewController:(UIViewController *)viewController
addingContraints:(BOOL)addingContraints ;
- (void)pushViewController:(UIViewController *)viewController
addingContraints:(BOOL)addingContraints
animated:(BOOL)withAnimation;
@end
@interface MyCustomNavigationController ()
#pragma mark - Managing transitions
@property (nonatomic, strong, readwrite) NSMutableArray * transitionTypes ; // to store the various transitions types
- (MyCustomNavigationControllerTransition)inverseTransitionType:(MyCustomNavigationControllerTransition)transitionType ; // to "invert" a transition type
@property (nonatomic, assign, readwrite) MyCustomTransitionManager * navigationManager ;
@end
@interface MyCustomTransitionManager : NSObject <UIViewControllerTransitioningDelegate>
@property (nonatomic, assign, readwrite) MyCustomNavigationControllerTransition transitionType ;
/**
Some parameters
*/
@property (nonatomic, strong, readwrite) UIColor * backgroundColor ;
@property (nonatomic, assign, readwrite) CGFloat opacity ;
@property (assign, nonatomic, readwrite) NSTimeInterval durationTransition ;
@property (assign, nonatomic, readwrite) CGFloat scale ;
@property (assign, nonatomic, readwrite) CGFloat velocity ;
@end
Questions :
- l'abandon de iOS 6, c'est ok ? (maintenant que y'a iOS8)
- la notion de content view controller est-elle juste informelle ? (c'est-à -dire il n'y a pas de classe UIContentViewController)
- En gros, c'est quoi un content view controller ? C'est un VC qui a vocation à pusher et poper d'autres VC (les child VC) ?
- UIViewControllerTransitioningDelegate et UIViewControllerInteractiveTransitioning sont-ils deux objets distincts ? Je pense que je comprends à peu près UIViewControllerTransitioningDelegate mais je ne me suis pas encore penché sur UIViewControllerInteractiveTransitioning. La vidéo 218 de WWDC 2013 est très utile !
- Au niveau du style dans mes interfaces, avez-vous des conseils à me donner ?
- Vous confirmez bien que quand j'enlève un view d'un superview, les contraintes qui lient les deux sont aussi enlevées ?
- dans l'implementation de push, pop, je vais devoir ajouter/enlever des VCs à mon tableau de childViewControllers. Comment dois-je faire ça ? Via une API de UIViewController ou en manipulant directement le tableau ? Où dois-je faire ça ? Dans l'implémentation de MyCustomNavigationController ? Ou dans le delegate MyCustomTransitionManager ?
- Je pense que mes interfaces (y compris privées) ne sont pas complètes. Elles le seront que le .m sera fait. Voyez-vous des choses manquantes ou des problèmes qui vont se poser ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
beaucoup de questions . Comment j'aurais fais :
Je partirai sur une sous classe de UInavigationController.
1) Pour customiser les animations push, il faut redéfinir la méthode push dans la sous-classe.
2) Il suffit de dire au custom navigationController de cacher sa bare.
3) Pop interactive : redefinir la méthode pop.
Merci de ta réponse Samir.
Voilà aussi un lien intéressant : un projet github avec plein de transitions personnalisées. Je vais déjà voir ce que je peux en faire...
Le projet a plein de stars, ce qui est de bon augure...
https://github.com/ColinEberhardt/VCTransitionsLibrary
Mais attention ! Il y avait beaucoup de changements pour les transitions sous iOS 8. Regardez bien les docs et je vous conseillerais à regarder la vidéo 214 de WWDC 2014.
Et, jamais, jamais sous-classer UINavigationController >:D
Tu peux gérer la transition des ViewController à l'aide d'animations personnalisées apportées à la version iOS7. Il faut regarder ici :
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewControllerAnimatedTransitioning_Protocol/
Quelques articles bien utiles :
http://www.objc.io/issue-12/custom-container-view-controller-transitions.html
http://mathewsanders.com/animated-transitions-in-swift/
Pour répondre à quelques unes de tes questions.
• iOS6 je pense pas que ce soit utile si c'est une nouvelle application puisque 80% des devices qui se connectent sur l'app Store sont sous iOS8 et entre 15 et 17% sous iOS7. Je me souviens plus de l'url exacte où on pouvait voir ça mais je ne pense pas être loin de la vérité.
• pour ce que tu nommes ContentViewController tu trouveras les réponses à tes interrogations ici. Je trouve que c'est plutôt bien expliqué. : https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/AboutViewControllers/AboutViewControllers.html#//apple_ref/doc/uid/TP40007457-CH112-SW10
Pour ce que tu veux faire donc, utiliser juste les animations de transitions de vues contrôleurs semblent largement convenir à tes besoins si j'ai bien compris.
Pour quelle raison ne jamais sous-classer le UINavigationController ?
The UINavigationController class implements a specialized view controller that manages the navigation of hierarchical content. This navigation interface makes it possible to present your data efficiently and makes it easier for the user to navigate that content.
You generally use this class as-is but in iOS 6 and later you may subclass to customize the class behavior.
Effectivement. Je viens de achever une app qui contenait plusieurs transitions et qui se sont cassées de l'arrivée de iOS 8.
Il n'y a aucune raison de faire les transitions en dehors de la démarche qu'Apple nous fournisse. En plus, après avoir dû mettre dans la poubelle beaucoup de code qui fonctionne bien sous iOS 7 mais qui se plante sous iOS 8, je te dirais colas2 qu'il ne vaut pas la peine de réinventer la roue comme tu propose au-dessus.
Côté sous-classement de UINavigationController, j'en dois demander, pourquoi ? Oui, évidemment d'iOS 6, c'est possible, mais je demanderais si c'est jamais justifié.
En revanche, j'ai bien réussi à sous-classé UIStoryboardSegue pour que je puisse accomplir les transitions réutilisables.
Joanna, je serais intéressé de savoir ce qui a cassé avec ios8. Est-ce que c'est à cause de changement de coordonnées de UIScreen ?
J'ai vu la vidéo que tu m'as conseillée (je pense que la 228 est bien aussi, mais pas encore vu). J'ai l'impression que les API sont plus ou moins les mêmes mais que c'est le "engine" qui a changé (avec un nouvel objet qui gère les animations, si j'ai bien compris)
Je crois que oui, mais le projet s'est arrêté dès l'annonce de l'obligation pour les apps 64 bits, car nous avions une lib statique qui est toujours compilée sous Free Pascal et nous en attendions la version 64 bit pour que nous puissions progresser. Du coup, je n'ai pas pu l'occasion à travailler plus sur le projet.
Félicitations sur la découverte de 228, j'avais l'intention de t'en parler mais je n'étais pas encore arrivée.
C'est ça que j'ai compris. Il me faut organiser le temps pour le rechercher mais nous sommes en train de préparer pour un périple en cherchant une maison à acheter en Bretagne.
L'intro de https://github.com/C...nsitionsLibrary a l'air bien aussi. Le mec a codé plein de transitions et en intro de son projet github il fait un topo (=he briefly explains) sur le qui-que-quoi-où-comment des transitions.
Je vais lire ça de ce pas, après je regarderai la vidéo.
PS : si ça a cassé uniquement à cause de UIScreen ça doit être réparable facilement.
@Joanna : une super vidéo sur ça et sur d'autres sujets est :
https://developer.apple.com/tech-talks/videos/#3
ça ne mène pas à une seule vidéo. Tu parles plutôt de "Architecting Modern Apps, Part 1" ?
Oui c'est ça. La présentation du mec est super claire. Les UIMotionEffect je connaissais pas, c'est hyper simple, oh my god ! (je suis en train de la regarder)
Bon, je la regarderai plus tard.
Sinon, pour revenir au sujet initial, les meilleures références que j'ai trouvées (tuto + code) sont :
- http://www.objc.io/issue-12/custom-container-view-controller-transitions.html
et
- http://www.iosnomad.com/blog/2014/5/12/interactive-custom-container-view-controller-transitions
... d'où ta réticence à sous-classer NS[...]Controller ?