viewWillDisappear: określa, czy kontroler widoku jest wyświetlany, czy też jest wyświetlany kontroler widoku podrzędnego

Staram się znaleźć dobre rozwiązanie tego problemu. W metodzie kontrolera widoku -viewWillDisappear: muszę znaleźć sposób na określenie, czy jest to spowodowane tym, że kontroler widoku jest pchany na stos kontrolera nawigacyjnego, czy też dlatego, że kontroler widoku znika, ponieważ został popchnięty.

W tej chwili ustawiam flagi takie jak isShowingChildViewController ale robi się to dość skomplikowane. Jedyny sposób, w jaki mogę to wykryć, to metoda -dealloc.

Author: Michael Waterfall, 2009-11-29

12 answers

Możesz użyć następujących.

- (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");
  }
}

Jest to oczywiście możliwe, ponieważ stos kontrolerów widoku uinavigationcontroller (wystawiony przez właściwość viewcontrollers) został zaktualizowany do czasu wywołania viewWillDisappear.

 223
Author: Bryan Henry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-16 13:48:26

Myślę, że najprostszym sposobem jest:

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

Swift:

override func viewWillDisappear(animated: Bool)
{
    super.viewWillDisappear(animated)
    if isMovingFromParentViewController
    {
        print("View controller was popped")
    }
    else
    {
        print("New view controller was pushed")
    }
}
 122
Author: hacker2007,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-16 11:29:22

Z Dokumentacji Apple w UIViewController.h:

" te cztery metody mogą być użyte w wyglądzie kontrolera widoku wywołania zwrotne w celu ustalenia, czy jest prezentowany, odrzucany lub dodawany lub usunięty jako kontroler widoku potomnego. Na przykład kontroler widoku może sprawdzić, czy znika, ponieważ został odrzucony lub pęknięty zadając sobie pytanie w swoim viewWillDisappear: metoda sprawdzając expression ([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);

Więc tak, jedynym udokumentowanym sposobem, aby to zrobić jest następujący sposób:

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

Wersja Swift 3:

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

    if self.isBeingDismissed || self.isMovingFromParentViewController { 
    }
}
 53
Author: Shyam Bhat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-18 15:40:46

Jeśli chcesz tylko wiedzieć, czy twój widok jest wyrzucany, właśnie odkryłem, że self.navigationController jest nil w viewDidDisappear, gdy jest usuwany ze stosu kontrolerów. Więc to prosty test alternatywny.

(to odkrywam po wypróbowaniu różnych innych konturów. Dziwię się, że nie ma protokołu kontrolera Nawigacyjnego do rejestracji kontrolera widoku, który ma być powiadamiany o popach. Nie możesz użyć UINavigationControllerDelegate, ponieważ to naprawdę działa.)

 17
Author: dk.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-19 07:37:38

W Języku Swift:

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

    super.viewWillDisappear(animated)

}
 5
Author: user754905,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-18 22:19:58

Swift 3

override func viewWillDisappear(_ animated: Bool)
    {
        super.viewWillDisappear(animated)
        if self.isMovingFromParentViewController
        {
            //View Controller Popped
        }
        else
        {
            //New view controller pushed
        }
    }
 3
Author: Umair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-10 10:46:35

Uważam, że dokumentacja Apple na ten temat jest trudna do zrozumienia. To rozszerzenie pomaga zobaczyć stany w każdej nawigacji.

extension UIViewController {
    public func printTransitionStates() {
        print("isBeingPresented=\(isBeingPresented)")
        print("isBeingDismissed=\(isBeingDismissed)")
        print("isMovingToParentViewController=\(isMovingToParentViewController)")
        print("isMovingFromParentViewController=\(isMovingFromParentViewController)")
    }
}
 1
Author: Norman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-11 15:49:41

To pytanie jest dość stare, ale widziałem je przez przypadek, więc chcę opublikować best practice (afaik)

You can just do

if([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
 // view controller popped
}
 0
Author: user1396236,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-04 11:23:56

Dotyczy to iOS7 , nie wiadomo, czy dotyczy to innych. Z tego co wiem, w viewDidDisappear widok już się pojawił. Co oznacza, że gdy zapytasz self.navigationController.viewControllers otrzymasz nil. Więc po prostu sprawdź, czy to jest zero.

TL;DR

 - (void)viewDidDisappear:(BOOL)animated
 {
    [super viewDidDisappear:animated];
    if (self.navigationController.viewControllers == nil) {
        // It has been popped!
        NSLog(@"Popped and Gone");
    }
 }
 0
Author: Byte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-03 19:43:04

[[2]}Segues może być bardzo skutecznym sposobem radzenia sobie z tym problemem w iOS 6+. Jeśli podałeś konkretnemu segue identyfikator w Interface Builder, możesz go sprawdzić w 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
    }
}
 0
Author: Kyle Clegg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-04 15:50:51

Zakładam, że masz na myśli, że twój widok jest przesuwany w dół stosu kontrolera nawigacyjnego przez popychanie nowego widoku, kiedy mówisz pchnięcie na stosie. Sugerowałbym użycie metody viewDidUnload, aby dodać NSLog, aby napisać coś do konsoli, abyś mógł zobaczyć, co się dzieje, możesz dodać NSLog do viewWillDissappeer.

 -1
Author: Aaron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-29 20:25:56

Tutaj jest kategoria, która pozwoli osiągnąć to samo, co odpowiedź sbrocket:

Header:

#import <UIKit/UIKit.h>

@interface UIViewController (isBeingPopped)

- (BOOL) isBeingPopped;

@end

Źródło:

#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
 -1
Author: bbrame,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-19 21:08:46