2010-04-13 18 views
8

Tengo un botón dentro del contenido de un UIPopoverController. Este botón ejecuta un método llamado myAction.ipad - descartar un UIPopoverController

MyAction tiene la forma

- (void) myAction:(id)sender 

así, miAccion recibe el identificador del botón de llamada.

Ahora, dentro de este método, me gustaría descartar el UIPopoverController, pero lo único que tengo es la identificación del botón de la persona que llama. Recuerde que el botón está dentro del UIPopoverController.

¿Hay alguna manera de descubrir la ID del UIPopoverController, dada la identificación del botón que ya tengo?

gracias.

Respuesta

19

Desafortunadamente no. Al menos, no dentro de las prácticas estándar. Es posible que puedas subir la pila de respuestas para encontrarlo, pero es un truco, tiene errores y es realmente muy complicado.

Si desea descartar un popover presionando un botón, un lugar relevante debe mantener una referencia al popover. Por lo general, ese sería el propietario del popover (no el controlador mostró dentro de el popover). Cuando se presiona el botón, puede enviar un mensaje al controlador propietario, que luego puede descartar el popover.

Puede que tengas la tentación de que el controlador que se muestra dentro del popover sea el propietario de su propio popover, pero codificar de esta manera es frágil, puede volverse desordenado (de nuevo) y puede retener bucles de modo que ninguno de los dos liberado.

+0

gracias. ¡Cambiaré el código! – SpaceDog

+3

El segundo párrafo es extremadamente importante en esta respuesta. Recuerde, de acuerdo con la Guía de programación de iPad: "Tenga en cuenta, sin embargo, que es su responsabilidad almacenar una referencia al controlador Popover para que pueda descartarlo. El sistema no proporciona uno por defecto". Por lo tanto, no hagas un "lanzamiento" en él (causará un bloqueo de todos modos) hasta que la vista principal haya entrado en la fase dealloc. (ese es mi método de seguridad). – Jann

+0

simplemente use [autodesculuntarVerControllerAnimated: YES completion: nil]; "El controlador de visualización de presentación es responsable de descartar el controlador de vista que presentó. Si llama a este método en el controlador de vista presentado, automáticamente reenvía el mensaje al controlador de vista que se presenta". –

4

Tengo esto funcionando, y no creo que sea un truco. Tengo una aplicación para iPad estándar con vista dividida. A continuación, agregué un método en mi controlador de detalles (el propietario del pop-up) para manejar el despido.

En la arquitectura de vista dividida estándar, tanto el controlador de vista raíz como el de detalles están disponibles a través del delegado de la aplicación. Así que hice clic en un botón dentro de la ventana emergente para llamar a un método que obtiene el delegado de la aplicación. Desde allí, invoco el método en el controlador de detalle para descartar el pop-up.

Este es el código para el método en el controlador de vista que se muestra dentro de la popover:

- (void) exitView: (id)sender { 
    MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate]; 

    [appDelegate.detailViewController exitDrill]; 
} 

A continuación, el método simple de despido a la vista en detalle Controlador:

- (void) exitDrill { 
    if(dtController != nil){ 
     [dtController dismissPopoverAnimated: YES]; 
     [dtController release]; 
    } 
} 

me gusta la capacidad de hacer esto porque me da una forma de mostrarle a un usuario cómo pueden salir de un estallido. Esto puede no ser necesario en futuras versiones de la aplicación; por ahora, aunque este paradigma aún es nuevo para la plataforma, prefiero dejar que los usuarios geneticen una pantalla de dos maneras diferentes para asegurarse de que minimizo la frustración.

5

Puede acceder al presentador popoverController accediendo a "popoverController" con KVC.

[[self valueForKey:@"popoverController"] dismissPopoverAnimated:YES] 
+1

Inteligente, pero ¿hay alguna posibilidad de que se etiquete como "uso de API privada" y se rechace la aplicación aunque técnicamente no esté utilizando una API privada? –

+0

Sí @Chintan. Potencialmente es rechazado por AppStore si detectan que su código está usando su "API privada". –

+0

@JasonMing Esto es lo único que funcionó para mí, y he pasado la mayor parte de 5 horas tratando de encontrar una solución. Muchas gracias ... –

0

Como Ed Marty ya escribió

Si desea borrar un popover pulsando un botón, un lugar relevante debería mantener una referencia a la popover

Esto es muy cierto ; sin embargo, al mostrar un UIPopoverController, la clase que abre el controlador popover mantiene este recurso ya. Entonces, lo que podrías hacer es usar esta clase como la clase delegada para tu Controlador Popover.

Para hacerlo, puede hacer lo siguiente, que utilizo en mi código. En la clase de abrir el popover, este es mi código:

- (void)showInformationForView:(Booking*)booking frame:(CGRect)rect 
{ 
    BookingDetailsViewController *bookingView = [[BookingDetailsViewController alloc] initWithStyle:UITableViewStyleGrouped booking:booking]; 
    [bookingView setDelegate:self]; 

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:bookingView]; 

    self.popController = [[UIPopoverController alloc] initWithContentViewController:navController]; 
    [self.popController setDelegate:self]; 
    [self.popController setPopoverContentSize:CGSizeMake(320, 320)]; 

    rect.size.width = 0; 

    [self.popController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES]; 
} 

- (void)dismissPopoverAnimated:(BOOL)animated 
{ 
    [self.popController dismissPopoverAnimated:animated]; 
} 

Entonces, ¿qué estoy haciendo aquí es la creación de un UINavigationController y el establecimiento de un BookingDetailsViewController como su rootViewController. Luego también agrego la clase actual como delegado a este BookingDetailsViewController.

Lo segundo que agregué es un método de destitución llamado dismissPopoverAnimated:animated.

En mi BookingDetailsViewController.h I añade el siguiente código:

[...] 
@property (nonatomic, strong) id delegate; 
[...] 

Y en mi BookingDetailsViewController.m He añadido este código:

[...] 

@synthesize delegate = _delegate; 

- (void)viewDidLoad 

{ 
    UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeView)]; 
    [self.navigationItem setRightBarButtonItem:closeButton]; 

    [super viewDidLoad]; 
} 

- (void)closeView 
{ 
    if ([self.delegate respondsToSelector:@selector(dismissPopoverAnimated:)]) { 
     [self.delegate dismissPopoverAnimated:YES]; 
    } 
    else { 
     NSLog(@"Cannot close the view, nu such dismiss method"); 
    } 
} 

[...] 

Lo que sucede es que cuando el botón "Cerrar" en el UINavigationController es presionado, se llama al método closeView. Este método verifica si el delegado responde al dismissPopoverAnimated:animated y si es así, lo llama. Si no responde a este método, mostrará un mensaje de registro y no hará nada más (por lo que no se bloqueará).

He escrito mi código usando ARC, por lo tanto no hay administración de memoria.

Espero que esto te haya ayudado.

Cuestiones relacionadas