tutorial life example containerviewcontroller container iphone cocoa-touch uikit

iphone - example - lifecycle viewcontroller ios



viewWillDisappear: determina si el controlador de vista se está copiando o está mostrando un controlador de subvista (12)

Estoy luchando por encontrar una buena solución a este problema. En el método view- -viewWillDisappear: del controlador de -viewWillDisappear: , necesito encontrar una manera de determinar si se debe a que un controlador de vista está siendo insertado en la pila del controlador de navegación, o si es porque el controlador de vista está desapareciendo porque se ha reventado.

En este momento estoy configurando indicadores como isShowingChildViewController pero se está isShowingChildViewController bastante complicado. La única forma en que creo que puedo detectarlo es en el método de -dealloc .


Aquí hay una categoría para lograr lo mismo que la respuesta de sbrocket:

Encabezamiento:

#import <UIKit/UIKit.h> @interface UIViewController (isBeingPopped) - (BOOL) isBeingPopped; @end

Fuente:

#import "UIViewController+isBeingPopped.h" @implementation UIViewController (isBeingPopped) - (BOOL) isBeingPopped { NSArray *viewControllers = self.navigationController.viewControllers; if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) { return NO; } else if ([viewControllers indexOfObject:self] == NSNotFound) { return YES; } return NO; } @end


Creo que la manera más fácil es:

- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if ([self isMovingFromParentViewController]) { NSLog(@"View controller was popped"); } else { NSLog(@"New view controller was pushed"); } }

Rápido:

override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParentViewController { print("View controller was popped") } else { print("New view controller was pushed") } }


De la documentación de Apple en UIViewController.h:

"Estos cuatro métodos se pueden usar en las devoluciones de llamada de apariencia de un controlador de vista para determinar si se presentan, descartan o agregan o eliminan como un controlador de vista hijo. Por ejemplo, un controlador de vista puede verificar si está desapareciendo porque se descartó o apareció preguntándose en su método viewWillDisappear: comprobando la expresión ([self isBeingDismissed] || [self isMovingFromParentViewController]) ".

- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);

- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);

Entonces, sí, la única manera documentada de hacerlo es de la siguiente manera:

- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if ([self isBeingDismissed] || [self isMovingFromParentViewController]) { } }

Swift 3 versión:

override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if self.isBeingDismissed || self.isMovingFromParentViewController { } }


En Swift:

override func viewWillDisappear(animated: Bool) { if let navigationController = self.navigationController { if !contains(navigationController.viewControllers as! Array<UIViewController>, self) { } } super.viewWillDisappear(animated) }


Encuentro que la documentación de Apple sobre esto es difícil de entender. Esta extensión ayuda a ver los estados en cada navegación.

extension UIViewController { public func printTransitionStates() { print("isBeingPresented=/(isBeingPresented)") print("isBeingDismissed=/(isBeingDismissed)") print("isMovingToParentViewController=/(isMovingToParentViewController)") print("isMovingFromParentViewController=/(isMovingFromParentViewController)") } }


Esta pregunta es bastante antigua, pero la vi por accidente, así que quiero publicar las mejores prácticas (afaik)

solo puedes hacer

if([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) // view controller popped }


Esto se aplica a iOS7 , no sé si se aplica a cualquier otro. Por lo que sé, en viewDidDisappear la vista ya se ha reventado. Lo que significa que cuando consultas self.navigationController.viewControllers obtendrás un nil . Así que solo revisa si eso es nulo.

TL; DR

- (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; if (self.navigationController.viewControllers == nil) { // It has been popped! NSLog(@"Popped and Gone"); } }


Puedes usar lo siguiente.

- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; NSArray *viewControllers = self.navigationController.viewControllers; if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) { // View is disappearing because a new view controller was pushed onto the stack NSLog(@"New view controller was pushed"); } else if ([viewControllers indexOfObject:self] == NSNotFound) { // View is disappearing because it was popped from the stack NSLog(@"View controller was popped"); } }

Esto es, por supuesto, posible porque la pila del controlador de vista de UINavigationController (expuesta a través de la propiedad viewControllers) se ha actualizado cuando se llama a viewWillDisappear.


Segues puede ser una forma muy efectiva de manejar este problema en iOS 6+. Si le ha dado un identificador particular en Interface Builder, puede verificarlo en prepareForSegue .

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"LoginSegue"]) { NSLog(@"Push"); // Do something specific here, or set a BOOL indicating // a push has occurred that will be checked later } }


Si solo quieres saber si tu vista se está reproduciendo, acabo de descubrir que self.navigationController es nil en viewDidDisappear , cuando se elimina de la pila de controladores. Entonces esa es una prueba alternativa simple.

(Esto lo descubrí después de probar todo tipo de otras contorsiones. Me sorprende que no haya un protocolo de controlador de navegación para registrar un controlador de vista para recibir notificaciones en emergencias. No puede usar UINavigationControllerDelegate porque eso realmente hace un trabajo de visualización real).


Supongo que quiere decir que su vista se mueve hacia abajo en la pila del controlador de navegación empujando una nueva vista cuando dice empujado a la pila. Yo sugeriría usar el método viewDidUnload para agregar una declaración NSLog para escribir algo en la consola para que pueda ver lo que está pasando, es posible que desee agregar un NSLog para viewWillDissappeer .


Swift 3

override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if self.isMovingFromParentViewController { //View Controller Popped } else { //New view controller pushed } }