Pregunta

Necesito saber cuándo mi controlador de vista está a punto de salir de una pila de navegación para poder realizar una acción.

No puedo usar -viewWillDisappear, porque se llama cuando el controlador de vista se mueve fuera de la pantalla por CUALQUIER motivo (como un nuevo controlador de vista que se empuja hacia arriba).

Necesito específicamente saber cuándo el controlador está a punto de abrirse.

Cualquier idea sería genial, gracias de antemano.

¿Fue útil?

Solución

No creo que haya un mensaje explícito para esto, pero podría subclasificar el UINavigationController y anular - popViewControllerAnimated (aunque no lo he intentado antes)

Alternativamente, si no hay otras referencias al controlador de vista, ¿podría agregar a su - dealloc?

Otros consejos

Anule el método viewWillDisappear en el VC presentado, luego verifique el indicador isMovingFromParentViewController dentro de la anulación y realice una lógica específica. En mi caso, estoy ocultando la barra de herramientas de los controladores de navegación. Todavía requiere que su VC presentado comprenda que fue empujado, aunque no es perfecto.

Intenta anular willMoveToParentViewController: (en lugar de viewWillDisappear: ) en su subclase personalizada de UIViewController .

  

Llamado justo antes de agregar o quitar el controlador de vista de un controlador de vista de contenedor.

- (void)willMoveToParentViewController:(UIViewController *)parent
{
    [super willMoveToParentViewController:parent];
    if (!parent) {
        // `self` is about to get popped.
    }
}

Afortunadamente, cuando se llama al método viewWillDisappear, viewController ya se ha eliminado de la pila, por lo que sabemos que viewController aparece porque ya no está en self.navigationController.viewControllers

Swift 4

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if let nav = self.navigationController {
        let isPopping = !nav.viewControllers.contains(self)
        if isPopping {
            // popping off nav
        } else {
            // on nav, not popping off (pushing past, being presented over, etc.)
        }
    } else {
        // not on nav at all
    }
}

Código original

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if ((self.navigationController) && 
        (![self.navigationController.viewControllers containsObject:self])) {
        NSLog(@"I've been popped!");
    }
}

Esto está funcionando para mí.

- (void)viewDidDisappear:(BOOL)animated
{
    if (self.parentViewController == nil) {
        NSLog(@"viewDidDisappear doesn't have parent so it's been popped");
        //release stuff here
    } else {
        NSLog(@"PersonViewController view just hidden");
    }
}

Puedes atraparlo aquí.

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

    if (viewController == YourAboutToAppearController) {
            // do something
    }
}

Esto se disparará justo antes de la visualización de la nueva Vista. Nadie se ha movido todavía. Uso todo el tiempo para hacer magia frente al asinine NavigationController. Puede configurar títulos y botones y hacer lo que sea allí.

Tengo el mismo problema. Intenté con viewDisDisappear, pero no tengo la función que se llama :( (no sé por qué, tal vez porque todo mi VC es UITableViewController). La sugerencia de Alex funciona bien pero falla si su controlador de navegación se muestra en la pestaña Más. En este caso, todos los VC de sus controladores de navegación tienen el NavigationController como UIMoreNavigationController, no el controlador de navegación que ha subclasificado, por lo que el navegador no le notificará cuando un VC esté a punto de aparecer.
Finalmente, resolví el problema con una categoría de UINavigationController, solo reescriba - (UIViewController *) popViewControllerAnimated: (BOOL) animado

- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
   NSLog(@"UINavigationController(Magic)");
   UIViewController *vc = self.topViewController;
   if ([vc respondsToSelector:@selector(viewControllerWillBePopped)]) {
      [vc performSelector:@selector(viewControllerWillBePopped)];
   }
   NSArray *vcs = self.viewControllers;
   UIViewController *vcc = [vcs objectAtIndex:[vcs count] - 2];
   [self popToViewController:vcc animated:YES];
   return vcc;}

Funciona bien para mí: D

Intenté esto:

- (void) viewWillDisappear:(BOOL)animated {
    // If we are disappearing because we were removed from navigation stack
    if (self.navigationController == nil) {
        // YOUR CODE HERE
    }

    [super viewWillDisappear:animated];
}

La idea es que al hacer estallar, el control de navegación del controlador de vista se establece en nulo. Entonces, si la vista iba a desaparecer, y ya tiene un control de navegación, concluí que estaba abierta. (podría no funcionar en otros escenarios).

No se puede garantizar que viewWillDisappear se invocará al aparecer, ya que no se menciona en los documentos. Lo intenté cuando la vista era superior y debajo de la vista superior, y funcionó en ambos.

Buena suerte Oded.

Puedes usar este:

if(self.isMovingToParentViewController)
{
    NSLog(@"Pushed");
}
else
{
    NSLog(@"Popped");
}

Subclase UINavigationController y anule popViewController :

Swift 3

protocol CanPreventPopProtocol {
    func shouldBePopped() -> Bool
}

class MyNavigationController: UINavigationController {
    override func popViewController(animated: Bool) -> UIViewController? {
        let viewController = self.topViewController

        if let canPreventPop = viewController as? CanPreventPopProtocol {
            if !canPreventPop.shouldBePopped() {
                return nil
            }
        }
        return super.popViewController(animated: animated)
    }

    //important to prevent UI thread from freezing
    //
    //if popViewController is called by gesture recognizer and prevented by returning nil
    //UI will freeze after calling super.popViewController
    //so that, in order to solve the problem we should not return nil from popViewController
    //we interrupt the call made by gesture recognizer to popViewController through
    //returning false on gestureRecognizerShouldBegin
    //
    //tested on iOS 9.3.2 not others
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        let viewController = self.topViewController

        if let canPreventPop = viewController as? CanPreventPopProtocol {
            if !canPreventPop.shouldBePopped() {
                return false
            }
        }

        return true
    }

}

Tal vez podría usar el método de protocolo UINavigationBarDelegate navigationBar: shouldPopItem.

Intente hacer esta verificación en vista desaparecerá if ([self.navigationController.viewControllers indexOfObject: self] == NSNotFound) { // ha aparecido el estallido de esta vista. }

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top