He insertado una vista en el controlador de navegación y, cuando presiono el botón Atrás, pasa automáticamente a la vista anterior. Quiero hacer algunas cosas cuando se presiona el botón Atrás antes de sacar la vista de la pila. ¿Cuál es la función de devolución de llamada del botón Atrás?
102
Respuestas:
La respuesta de William Jockusch resuelve este problema con un truco fácil.
fuente
En mi opinión la mejor solución.
Pero solo funciona con iOS5 +
fuente
Probablemente sea mejor anular el botón trasero para que pueda manejar el evento antes de que aparezca la vista para cosas como la confirmación del usuario.
en viewDidLoad crea un UIBarButtonItem y establece self.navigationItem.leftBarButtonItem en él pasando un sel
Luego, puede hacer cosas como generar un UIAlertView para confirmar la acción, luego abrir el controlador de vista, etc.
O en lugar de crear un nuevo botón trasero, puede ajustarse a los métodos delegados de UINavigationController para realizar acciones cuando se presiona el botón Atrás.
fuente
UINavigationControllerDelegate
no tiene métodos que son llamados cuando se pulsa el botón atrás.Esta es la forma correcta de detectar esto.
este método también se llama cuando se empuja la vista. Entonces, verificar parent == nil es para extraer el controlador de vista de la pila
fuente
Termino con estas soluciones. Cuando tocamos el botón de retroceso viewDidDisappear método llamado. podemos verificar llamando al selector isMovingFromParentViewController que devuelve verdadero. podemos devolver los datos (usando Delegate) .Espero que esto ayude a alguien.
fuente
[super viewDidDisappear:animated]
Tal vez sea un poco tarde, pero también quería el mismo comportamiento antes. Y la solución con la que elegí funciona bastante bien en una de las aplicaciones que se encuentran actualmente en la App Store. Como no he visto a nadie usar un método similar, me gustaría compartirlo aquí. La desventaja de esta solución es que requiere subclases
UINavigationController
. Aunque use el método Swizzling podría ayudar a evitar eso, no fui tan lejos.Entonces, el botón de retroceso predeterminado es administrado por
UINavigationBar
. Cuando un usuario toca el botón de retroceso,UINavigationBar
pregúntele a su delegado si debería abrir la parte superiorUINavigationItem
llamandonavigationBar(_:shouldPop:)
.UINavigationController
en realidad implementa esto, pero no declara públicamente que lo adoptaUINavigationBarDelegate
(¿por qué?). Para interceptar este evento, cree una subclase deUINavigationController
, declare su conformidadUINavigationBarDelegate
e implementenavigationBar(_:shouldPop:)
. Regresetrue
si el elemento superior debe aparecer. Regresefalse
si debe quedarse.Hay dos problemas. La primera es que debes llamar a la
UINavigationController
versión denavigationBar(_:shouldPop:)
en algún momento. PeroUINavigationBarController
no lo declara públicamente de conformidadUINavigationBarDelegate
, intentar llamarlo resultará en un error de tiempo de compilación. La solución con la que fui es usar el tiempo de ejecución de Objective-C para obtener la implementación directamente y llamarla. Por favor, avíseme si alguien tiene una mejor solución.El otro problema es que
navigationBar(_:shouldPop:)
se llama primero y siguepopViewController(animated:)
si el usuario toca el botón Atrás. El orden se invierte si el controlador de vista se abre al llamarpopViewController(animated:)
. En este caso, utilizo un valor booleano para detectar sipopViewController(animated:)
se llama antes, lonavigationBar(_:shouldPop:)
que significa que el usuario ha pulsado el botón Atrás.Además, hago una extensión de
UIViewController
para permitir que el controlador de navegación pregunte al controlador de vista si debe aparecer si el usuario toca el botón Atrás. Los controladores de View pueden regresarfalse
y realizar las acciones necesarias y llamarpopViewController(animated:)
más tarde.Y en su vista controladores, implemente
shouldBePopped(_:)
. Si no implementa este método, el comportamiento predeterminado será abrir el controlador de vista tan pronto como el usuario toque el botón de retroceso como de costumbre.Puedes ver mi demo aquí .
fuente
Para "ANTES de quitar la vista de la pila":
fuente
Hay una forma más apropiada que preguntar a viewControllers. Puede hacer que su controlador sea un delegado de la barra de navegación que tiene el botón Atrás. He aquí un ejemplo. En la implementación del controlador donde desea manejar la presión del botón Atrás, dígale que implementará el protocolo UINavigationBarDelegate:
Luego, en algún lugar de su código de inicialización (probablemente en viewDidLoad) haga que su controlador sea el delegado de su barra de navegación:
Finalmente, implemente el método shouldPopItem. Este método se llama justo cuando se presiona el botón Atrás. Si tiene varios controladores o elementos de navegación en la pila, probablemente querrá comprobar cuál de esos elementos de navegación aparece (el parámetro del elemento), para que solo haga sus cosas personalizadas cuando lo espera. He aquí un ejemplo:
fuente
Si no puede utilizar "viewWillDisappear" o un método similar, intente crear una subclase de UINavigationController. Esta es la clase de encabezado:
Clase de implementación:
Por otro lado, debe vincular este viewController a su NavigationController personalizado, por lo que, en su método viewDidLoad para su viewController habitual, haga esto:
fuente
Aquí hay otra forma en que implementé (no la probé con una secuencia de desenrollado, pero probablemente no se diferenciaría, como otros han declarado con respecto a otras soluciones en esta página) para que el controlador de vista principal realice acciones antes que el VC secundario que empujó sale de la pila de vistas (utilicé esto un par de niveles hacia abajo del UINavigationController original). Esto también podría usarse para realizar acciones antes de que se presione el childVC. Esto tiene la ventaja adicional de trabajar con el botón de retroceso del sistema iOS, en lugar de tener que crear un UIBarButtonItem o UIButton personalizado.
Haga que su VC padre adopte el
UINavigationControllerDelegate
protocolo y se registre para mensajes delegados:Implemente este
UINavigationControllerDelegate
método de instancia enMyParentViewController
:Si especifica una función de devolución de llamada específica en el
UINavigationControllerDelegate
método de instancia anterior}
fuente
Esto es lo que me funciona en Swift:
fuente
Si está usando un Storyboard y viene de una transición de empuje, también puede simplemente anular
shouldPerformSegueWithIdentifier:sender:
.fuente