viewWillDisappear:确定是正在弹出视图控制器还是正在显示子视图控制器

Mic*_*all 132 iphone cocoa-touch uiviewcontroller uikit ios

我很难找到解决这个问题的好方法.在视图控制器的-viewWillDisappear:方法中,我需要找到一种方法来确定是否因为视图控制器被推到导航控制器的堆栈上,或者是否因为视图控制器因弹出而消失.

目前我正在设置标志,isShowingChildViewController但它变得相当复杂.我认为我可以检测它的唯一方法是在-dealloc方法中.

Bry*_*nry 228

您可以使用以下内容.

- (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");
  }
}
Run Code Online (Sandbox Code Playgroud)

当然,这是可能的,因为在调用viewWillDisappear时,UINavigationController的视图控制器堆栈(通过viewControllers属性公开)已经更新.

  • 自iOS 5以来,这个答案已经过时.下面提到的`-isMovingFromParentViewController`方法允许您测试是否显式弹出视图. (22认同)
  • @Sbrocket有一个原因你没有`![viewControllers containsObject:self]`而不是`[viewControllers indexOfObject:self] == NSNotFound`?款式选择? (4认同)
  • 完善!我不知道为什么我没想到这一点!我想我不认为堆栈会被改变,直到调用消失的方法!谢谢 :-) (2认同)

RTa*_*che 129

我认为最简单的方法是:

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

迅速:

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

  • 对于iOS7,我必须再次检查[self.navigationController.viewControllers indexOfObject:self] == NSNotFound,因为后台应用程序也将通过此测试,但不会从导航堆栈中删除self. (3认同)
  • Apple提供了一种记录在案的方法 - http://stackoverflow.com/a/33478133/385708 (2认同)

Shy*_*hat 58

来自UIViewController.h中的Apple文档:

"这四种方法可以在视图控制器的外观回调中使用,以确定它是作为子视图控制器呈现,关闭,还是添加或删除.例如,视图控制器可以检查它是否因为被解除而消失或通过检查表达式([self isBeingDismissed] || [self isMovingFromParentViewController])在其viewWillDisappear:方法中询问自己."

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

所以是的,唯一记录的方法是通过以下方式:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if ([self isBeingDismissed] || [self isMovingFromParentViewController]) {
    }
}
Run Code Online (Sandbox Code Playgroud)

Swift 3版本:

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

    if self.isBeingDismissed || self.isMovingFromParentViewController { 
    }
}
Run Code Online (Sandbox Code Playgroud)


dk.*_*dk. 18

如果你只是想知道你的观点是否得到弹出,我才发现,原来self.navigationControllernilviewDidDisappear,当它从控制器的堆栈中删除.所以这是一个简单的替代测试.

(这是我在尝试各种其他扭曲之后发现的.我很惊讶没有导航控制器协议来注册视图控制器以便在弹出窗口上通知.你不能使用,UINavigationControllerDelegate因为它实际上是真正的显示工作.)


小智 14

斯威夫特4

override func viewWillDisappear(_ animated: Bool)
    {
        super.viewWillDisappear(animated)
        if self.isMovingFromParent
        {
            //View Controller Popped
        }
        else
        {
            //New view controller pushed
        }
    }
Run Code Online (Sandbox Code Playgroud)


use*_*905 6

在Swift中:

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

    super.viewWillDisappear(animated)

}
Run Code Online (Sandbox Code Playgroud)