2008-10-28 22 views
7

Me estaba rascando la cabeza con esto hace una semana, y ahora con un poco más de experiencia Cocoa en mi haber siento que tengo una idea de lo que podría estar pasando.¿ParentViewController es siempre un controlador de navegación?

Estoy haciendo una aplicación que es manejada por un UINavigationController. En AppDelegate, creo una instancia de esta clase, usando "página 1" como el Controlador de Root View.

UINavigationController *aNavigationController = [[UINavigationController alloc] 
    initWithRootViewController:page1ViewController]; 

Ahora aquí es donde estoy teniendo el problema. Desde la "página 1" me gustaría utilizar un controlador de vista modal que se desliza sobre la interfaz y luego desaparece una vez que el usuario ha realizado una edición. Hago que el uso de un código como éste, en el interior de Page1ViewController:

[self presentModalViewController:myModalViewController animated:YES]; 

Cuando el controlador de vista modal se ha ido, quiero un valor en "Página 1" para cambiar sobre la base de lo que el usuario introduce en el controlador de vista modal. Por lo tanto, he escrito algo de código como este, que reside en el controlador de vista modal:

[self.parentViewController dismissModalViewControllerAnimated:YES]; 
[self.parentViewController doSomethingPleaseWithSomeData:someData]; 

La actualización a la página 1 no estaba ocurriendo, y me llevó mucho tiempo darse cuenta de que el mensaje "doSomethingPleaseWithSomeData" era no se envía a Page1ViewController, sino al Controlador de navegación.

¿Esto es de esperar al usar los controladores de navegación? ¿Tal vez configuré algo incorrectamente? ¿Hay alguna manera fácil de acceder al Controlador de Vista que quiero (en este caso, Page1ViewController)?

Respuesta

14

Recomendaría usar el patrón de delegación para resolver su problema. Crear una propiedad

@property (nonatomic, assign) id <MyModalViewDelegate> delegate; 

Y el correspondiente protocolo de

@protocol MyModalViewDelegate 
@optional 
    - (void)myModalViewControllerDidFinish:(MyModalViewController *)aModalViewController; 
@end 

Cuando el usuario termina con su punto de vista (por ejemplo, grifos el botón de guardar), envía este mensaje:

if ([self.delegate respondsToSelector:@selector(myModalViewControllerDidFinish:)]) 
    [self.delegate myModalViewControllerDidFinish:self]; 

último, se configuran el delegado al controlador de vista que debe administrar todo, y se le notificará cuando finalice el controlador de vista. Tenga en cuenta que necesitará su controlador de vista para cerrar el controlador de vista modal. Pero, lógicamente, eso tiene sentido, ya que fue el objeto que presentó el controlador de vista modal en primer lugar.

Así resuelve Apple este problema, por ejemplo, en UIImagePickerController y UIPersonPickerController.

4

Hay varias formas de hacerlo. La más sencilla es probablemente sólo para añadir un alojamiento UIViewController en myModalViewController y la puso a page1Controller antes de presentarlo:

myModalViewController.logicalParent = self; //page1Controller 
[self presentModalViewController:myModalViewController animated:YES]; 

Sólo asegúrese de añadir la variable de instancia @property apropiado y @synthesize para logicalParent a myModalViewController, a continuación, tendrá una forma de comunicar los datos al ViewController que activó el diálogo modal. Esto también es para pasar datos de ida y vuelta entre los diferentes niveles de navegación antes de empujarlos y colocarlos en la pila.

Lo importante de lo que preocuparse al hacer esto es que es fácil obtener bucles de retención si no tiene cuidado. Dependiendo de cómo se estructura esto, es posible que necesite usar propiedades de asignación.

+0

¡Realiza exactamente lo que quiero, gracias! Soy nuevo en Cocoa, pero no en MVC. El problema es que, siendo un desarrollador web de Java, casi siempre me olvido de que los controladores en "C" PUEDEN interactuar entre ellos. – bpapa

+0

Una buena respuesta, pero ¿por qué es este el caso? Claramente * no * ese caso es que parentViewController de la vista modal es el controlador de navegación en cualquier sentido lógico (page1Controller es el controlador que solicita la visualización modal), entonces, ¿por qué Cocoa Touch lo configuró de esta manera? –

1

Acabo de encontrarme con este mismo problema. Definitivamente parece que si coloca un UIViewController incrustado en un NavigationController, cuando, desde ese UIViewController, presente otro UIViewController de manera modal, el presente considera que el presentador es NavigationController. En otras palabras, parentViewController es incorrecto.

Apuesto a que esto es un error: o eso, o la documentación parece incompleta. Preguntaré.

1

Acabo de pasar por el mismo problema. Creo que esto es un error. Mi situación es la siguiente: Una jerarquía de navegación con controladores de vista A, B y C en este orden. En C hay un botón que abriría un controlador de vista modal llamado D. Una vez que se presenta D, el controlador de navegación descarta C de su jerarquía, lo cual es un comportamiento terrible. Una vez que se descarta D, el controlador de navegación instancia el un nuevo controlador de vista tipo C y lo empuja a su jerarquía para recuperar el original. Terrible. Mi solución es la piratería de la jerarquía de navegación de esta manera (una muy mala solución, pero funciona bien con una matriz de 2 dimensiones se podría aplicar modales de apilamiento.):

- (void)presentModalViewController:(UIViewController *)c { 
    [self.navigationHierarchy removeAllObjects]; 
    [self.navigationHierarchy addObjectsFromArray:[navigation viewControllers]]; 
    [navigation setViewControllers:[NSArray array] animated:YES]; 
    [navigation presentModalViewController:c animated:YES]; 
} 

- (void)dismissModalViewController { 
    [navigation dismissModalViewControllerAnimated:YES]; 
    [navigation setViewControllers:[NSArray arrayWithArray:self.navigationHierarchy] animated:YES]; 
} 

Estos dos métodos se definen en el que mantener la hiererchy principal de navegación: el delegado de la aplicación. La navegación y la jerarquía de navegación se definen de esta manera:

NSMutableArray *navigationHierarchy; 
UINavigationController *navigation; 
Cuestiones relacionadas