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
}
}