2009-10-12 26 views
16

Tengo un UITableViewController que inicia un UIViewController y me gustaría atrapar cada vez que se presiona el botón Atrás en el controlador secundario, que es la clase que se deriva de 'UIViewController'. Puedo cambiar el título del Botón Atrás pero estableciendo los valores de acción & de destino cuando se ignora la configuración del BackBarButtonItem. ¿Cuál es una forma de recibir algún tipo de notificación de que el botón Atrás fue tocado?Cómo atrapar el evento del botón Atrás

- (void)showDetailView 
{ 
    // How I'm creating & showing the detail controller 
    MyViewController *controller = [[MyViewController alloc] initWithNibName:@"MyDetailView" bundle:nil]; 

    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Pages" 
          style:UIBarButtonItemStyleBordered 
          target:self          
          action:@selector(handleBack:)]; 

    self.navigationItem.backBarButtonItem = backButton; 
    [backButton release]; 

    [self.navigationController pushViewController:controller animated:animated]; 
    [controller release]; 

} 

- (void)handleBack:(id)sender 
{ 
    // not reaching here 
    NSLog(@"handleBack event reached"); 
} 
+1

Para las personas que buscan una solución eficaz iOS 5+: http: // stackoverflow.com/a/13370744/1072846 – Eric

Respuesta

1

Usted puede hacer su propio botón y colocarlo como el leftBarButtonItem. Luego haga que llame a su método donde puede hacer lo que sea, y llame al [self.navigationController popViewController... usted mismo

+1

el 'leftBarButtonItem' no mostrará el mismo estilo de botón con el triángulo mirando hacia los lados. En cambio, creo que el botón será cuadrado. ¿Hay alguna manera de hacer que se vea como el botón típico y atrapar el evento? –

+0

Puede crear su propia imagen de flecha izquierda si conoce el ancho del texto de su botón, o puede crearla programáticamente, imitando lo que hace Apple. – coneybeare

18

Puede implementar el método viewWillDisappear de UIViewController. Se llama a esto cuando su controlador está a punto de desaparecer (ya sea porque se colocó otro en la pila del controlador de navegación o porque se presionó el botón 'volver').

Para determinar si la vista está desapareciendo debido al botón de retroceso se presiona, se puede utilizar una bandera personalizada que se establece siempre que se presiona un nuevo controlador en el controlador de navegación, como se muestra a continuación

- (void)viewWillDisappear:(BOOL)animated { 
    [super viewWillDisappear:animated]; 
    if (viewPushed) { 
     viewPushed = NO; // Flag indicates that view disappeared because we pushed another controller onto the navigation controller, we acknowledge it here 
    } else { 
     // Here, you know that back button was pressed 
    } 
} 

Y siempre que se presiona un nuevo controlador de vista, tendría que recordar a establecer también que la bandera ...

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    ... 
    viewPushed = YES; 
    [self.navigationController pushViewController:myNewController animated:YES]; 
    ... 
} 
+0

¿Cómo puede saber que la vista no desapareció porque otro botón invocó una vista secundaria? Quiero saber solo cuando se presiona el botón "Atrás". –

+0

En casos como este, configuré una bandera en didSelectRowAtIndexPath: (donde generalmente inserta un nuevo controlador en el controlador de navegación). viewWillDisappear puede entonces inspeccionar ese indicador y deducir si el botón Atrás fue presionado o no –

+0

Eso todavía no soluciona el problema que Justin señaló; Con su bandera sabrá cómo nació la vista, pero eso no significa que sea la única forma en que desaparecerá. – kbanman

17

ha sido un tiempo desde que este se le pidió, pero me acaba de intentar hacerlo yo mismo. He utilizado una solución similar a Zoran de, sin embargo en lugar de usar una bandera que hice esto:

- (void)viewWillDisappear: (BOOL)animated 
{ 
    [super viewWillDisappear: animated]; 
    if (![[self.navigationController viewControllers] containsObject: self]) 
    { 
     // the view has been removed from the navigation stack, back is probably the cause 
     // this will be slow with a large stack however. 
    } 
} 

creo que no pasa por los problemas con las banderas y la OMI sin embargo, no es más limpio, más eficiente (si hay un montón de artículos en el controlador de navegación).

+6

Es posible que pueda usar '[self.navigationController.viewControllers indexOfObjectIdenticalTo: self]! = NSNotFound' en lugar de' containsObject', que solo compararía la dirección del puntero. –

+0

Comprobó esto: Funciona. –

+1

Si su controlador está dentro de otro contenedor, tendrá que comparar a través de: "indexOfObjectIdenticalTo: self.parentViewController", que no sea eso, funciona. – marmor

0
{ 
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"back" 
                    style:UIBarButtonItemStyleBordered 
                    target:self                    
                    action:@selector(handleBack:)]; 
    self.navigationItem.leftBarButtonItem = backButton; 
    [backButton release]; 
    [self filldata]; 
    [super viewDidLoad]; 
} 

basta con sustituir backBarButtonItem con leftBarButtonItem

8

utilizo este código:

- (void) viewWillDisappear:(BOOL)animated { 

    if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) 
    { 
     // your view controller already out of the stack, it meens user pressed Back button 
    } 
} 

pero esto no es real cuando el usuario presiona el botón barra de pestañas y aparece a raíz del controlador de vista un solo paso. Para esta situación utilizar este:

[[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(viewControllerChange:) 
               name:@"UINavigationControllerWillShowViewControllerNotification" 
               object:self.navigationController]; 


- (void) viewControllerChange:(NSNotification*)notification { 

    NSDictionary* userInfo = [notification userInfo]; 

    if ([[userInfo objectForKey:@"UINavigationControllerNextVisibleViewController"] isKindOfClass:[<YourRootControllerClass> class]]) 
    { 
     // do your staff here 
    } 
} 

No se olvide a continuación:

[[NSNotificationCenter defaultCenter] removeObserver:self 
                name:@"UINavigationControllerWillShowViewControllerNotification" 
               object:self.navigationController]; 
12

En mi opinión, la mejor solución.

- (void)didMoveToParentViewController:(UIViewController *)parent 
{ 
    if (![parent isEqual:self.parentViewController]) { 
     NSLog(@"Back pressed"); 
    } 
} 

pero sólo funciona con iOS5 +

+0

Esta es la mejor solución, creo, ya que es más autónoma. – canhazbits

+0

dónde escribir esto – NaXir

-2

Sólo tiene que utilizar viewDidDisappear lugar. Se llamará perfectamente en cualquier escenario.

Estamos basando su gestión del ciclo de vida en viewDidAppear y viewDidDisappear. Si conoces Android: ambos son comparables a los métodos onResume y onPause. Pero hay una diferencia cuando se trata de bloquear la pantalla o presionar el botón de inicio en iOS.

Cuestiones relacionadas