Pregunta

Tengo un UIViewController & # 8212; vamos a llamarlo "FormController" & # 8212; que es simplemente una forma que edita un objeto. Quiero usarlo en 2 situaciones diferentes:

  1. Crear un nuevo objeto & # 8212; & nbsp; utilizando el método presentModalViewController de UINavigationController: .

  2. Edición de un objeto existente & # 8212; & nbsp; empuje el controlador de vista a la pila UINavigationController, sin utilizar un método de diálogo.

Hay una ligera diferencia en que, en la situación modal, me gustaría tener una barra de herramientas con "Cancelar" y "Hecho" botones, mientras que en la situación de pila me gustaría tener la barra de navegación proporcionada por UINavigationController.

Esto sería similar a la aplicación Contactos donde el " Nuevo contacto " y el " Editar contacto " Las pantallas parecen usar el mismo controlador de vista, pero el formulario Nuevo contacto se presenta modalmente mientras la pantalla Editar se empuja a la pila de navegación.

Mi pregunta es: ¿Cuál es la mejor manera de manejar ambas situaciones sin tener que escribir 2 controladores de vista separados, pero en su mayoría idénticos?

Pensé en crear un " ModalFormController " que encapsula el desnudo " FormController " a través de la composición y agrega una barra de herramientas, pero leí en algún lugar de los documentos que Apple no recomienda los controladores de vista de anidación.

¿Fue útil?

Solución

Lo que hago (a veces) es configurar un enum que especifica el tipo de controlador de vista.

Por ejemplo, puede tener dos tipos: un tipo Edit y un tipo Add (" new ").

El tipo Agregar se implementa a través de un controlador de vista modal, mientras que el tipo Editar se inserta en una pila de navegación existente.

En el método -viewDidLoad: del controlador de vista, simplemente hago un árbol switch / case que configura el título y otras características de apariencia según la enumeración de tipos especificada anteriormente .

Lo bueno de esto es que es fácil agregar un nuevo tipo. La desventaja es que el árbol condicional para entregar esta enumeración puede complicarse rápidamente, dependiendo de cuán diferentes sean los tipos.

Pero el árbol switch / case hace que sea mucho más fácil de administrar.

Entonces, depende de lo que intentes hacer con los dos tipos. Pero definitivamente es factible.

Otros consejos

¿Por qué no usar subclases? Convierta ModalCreateFormController en una subclase de EditFormController y maneje las cosas específicas del modo en la subclase.

Además de tener una propiedad explícita en el controlador de vista (como sugiere Alex Reynolds), otros dos enfoques que se me ocurren son:

  1. Si tiene algún tipo de objeto modelo que está editando, solicite su estado actual. Si alguna vez se ha guardado, entonces estás en modo de edición. De lo contrario, está en modo de creación.

  2. Observe el valor de la propiedad parentViewController del controlador. Si se trata de una instancia de UINavigationController , estás en la pila de navegación. Si se le muestra modalmente, será una instancia de su controlador de lista.

Ug, odio los ivars adicionales ...

Yo uso esto en su lugar:

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

        //Modal

    }else{

        //Pushed

    }

Es un truco, pero estamos usando la lógica de que si el controlador de vista ofensivo es el primero en la pila, no puedes volver atrás. En realidad, estamos ignorando el hecho de si se muestra modalmente en absoluto.

Tuve que hacer esto muchas veces en mi aplicación y después de probar un par de formas diferentes de hacerlo, incluidas las subclases modales & amp; Clases auxiliares modales reutilizables que utilizaban forwardInvocation. Encontré que el mejor patrón era hacer un método que contengaModalViewController cada controlador de vista que (generalmente) crea y devuelve un UINavigationController para que la persona que llama lo use con presentModalViewController.

En la mayoría de los casos, este método crea y devuelve un UINavigationController con self como controlador de vista raíz (con llamadas repetidas al método que comprueban self.navigationController y lo devuelven si no es nulo). En otros casos, hice un controlador raíz ficticio primero y me presioné en segundo lugar para obtener un botón de retroceso. Luego se puede usar un truco para atrapar el botón de retroceso presionar: http: // smallduck .wordpress.com / 2010/10/05 / intercepting-uinavigationcontroller /

En algunos casos, la vista no necesita una barra de navegación, por lo que este método solo ajusta algunas banderas y regresa self. Incluso encontré en algunos casos que sí necesitaba una barra de navegación que era más simple hacer que ese método invocara self.view, luego modificara la jerarquía de vista para agregar una UINavigationBar y nuevamente regresar self. Pero en cualquier caso, la configuración a menudo está aislada de ese método, y la persona que llama lo maneja igual en cada caso.

Apple explica cómo funciona la aplicación de contactos bajo el capó:

  

Para permitir que se use una clase de controlador de vista personalizada para mostrar y editar contenido, anule el método setEditing: animated: .

Obtiene algunas funciones de forma gratuita, p. Botón Editar / Listo .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top