Question

J'ai un contrôleur UIViewController & # 8212; appelons-le "FormController". & # 8212; qui est simplement une forme qui édite un objet. Je veux l'utiliser dans 2 situations différentes:

  1. Création d'un nouvel objet & # 8212; & nbsp; à l'aide de la méthode presentModalViewController: de UINavigationController.

  2. Modification d'un objet existant & # 8212; & nbsp; placez le contrôleur de vue sur la pile UINavigationController, sans utiliser de méthode de dialogue.

Il existe une légère différence en ce que, dans la situation modale, j'aimerais une barre d’outils avec " Annuler " et " Terminé " boutons, alors que dans la situation de pile je voudrais juste avoir la barre de navigation fournie par UINavigationController.

Cela serait similaire à l'application Contacts où l'option "Nouveau contact" et le " Modifier contact " les écrans semblent utiliser le même contrôleur de vue, mais le formulaire Nouveau contact est présenté sous forme modale, tandis que l'écran Modifier est placé dans la pile de navigation.

Ma question est la suivante: quel est le meilleur moyen de gérer ces deux situations sans avoir à écrire deux contrôleurs de vue distincts mais essentiellement identiques?

J'ai pensé créer un " ModalFormController " qui encapsule le "FormController" dépouillé; via la composition et ajoute une barre d’outils, mais j’ai lu quelque part dans la documentation que Apple ne recommande pas l’imbrication des contrôleurs de vue.

Était-ce utile?

La solution

Ce que je fais (parfois) consiste à configurer un enum qui spécifie le type du contrôleur de vue.

Par exemple, vous pouvez avoir deux types: un type Modifier et un type Ajouter ("nouveau").

Le type Add est implémenté via un contrôleur de vue modale, tandis que le type Modifier est placé dans une pile de navigation existante.

Dans la méthode -viewDidLoad: du contrôleur de vue, je crée simplement une arborescence switch / case qui définit le titre et d'autres caractéristiques d'apparence en fonction de l'énumération de type spécifiée ci-dessus. .

La bonne chose à ce sujet est qu’il est facile d’ajouter un nouveau type. L'inconvénient est que l'arborescence conditionnelle pour la gestion de cette énumération peut se compliquer rapidement, en fonction de la diversité des types.

Mais l'arborescence switch / case en facilite la gestion.

Cela dépend donc de ce que vous essayez de faire avec les deux types. Mais c’est tout à fait faisable.

Autres conseils

Pourquoi ne pas utiliser le sous-classement? Faites de ModalCreateFormController une sous-classe de EditFormController et gérez les éléments propres à un modal dans la sous-classe.

En plus d'avoir une propriété explicite sur le contrôleur de vue (comme le suggère Alex Reynolds), deux autres approches qui me viennent à l'esprit sont les suivantes:

  1. Si vous modifiez un type d'objet de modèle, demandez-lui son état actuel. Si cela a déjà été enregistré, alors vous êtes en mode édition. Sinon, vous êtes en mode création.

  2. Regardez la valeur de la propriété parentViewController du contrôleur. S'il s'agit d'une instance de UINavigationController , vous vous trouvez dans la pile de navigation. Si vous êtes affiché en mode modal, ce sera une instance de votre contrôleur de liste.

Ug, je déteste les ivars supplémentaires & # 8230;

J'utilise ceci à la place:

if([[self.navigationController viewControllers] objectAtIndex:0] == self){

        //Modal

    }else{

        //Pushed

    }

C'est un peu un bidouillage, mais nous utilisons la logique selon laquelle si le contrôleur de vue incriminé est le premier de la pile, vous ne pouvez pas revenir en arrière. En fait, nous ignorons si cela est affiché modalement.

Je devais le faire plusieurs fois dans mon application et après avoir essayé différentes façons de le faire, y compris des sous-classes modales & amp; classes d'assistants modaux réutilisables qui utilisaient forwardInvocation. J'ai trouvé que le meilleur modèle consistait à créer une méthode contenantModalViewController que chaque contrôleur de vue crée (généralement) et renvoie un UINavigationController que l'appelant utilisera avec presentModalViewController.

Dans la plupart des cas, cette méthode génère et retourne un UINavigationController avec self en tant que contrôleur de vue racine (avec des appels répétés à la méthode vérifiant self.navigationController et le renvoie si ce n'est pas nul). Dans d’autres cas, j’ai créé un contrôleur racine factice d’abord, puis une seconde fois afin d’obtenir un bouton Précédent. Ensuite, une astuce peut être utilisée pour intercepter le bouton Précédent: http: // smallduck .wordpress.com / 2010/10/05 / intercepting-uinavigationcontroller /

Dans certains cas, la vue n’a pas besoin de barre de navigation. Cette méthode ajuste donc simplement certains indicateurs et revient à elle-même. J'ai même constaté que, dans certains cas, qui nécessitaient une barre de navigation, il était plus simple d'invoquer self.view avec cette méthode, puis d'ajuster la hiérarchie des vues pour ajouter un UINavigationBar, puis de revenir à self. Mais dans tous les cas, la configuration est souvent isolée de cette méthode et l'appelant la gère de la même manière.

Apple explique le fonctionnement de l'application de contacts sous le capot:

  

Pour permettre à une classe de contrôleur de vue personnalisée d'être utilisée à la fois pour afficher et modifier du contenu, substituez la méthode setEditing: animated: .

Certaines fonctionnalités sont gratuites, par exemple. bouton Modifier / Terminé .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top