首页 文章

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

提问于
浏览
129

我需要找到一种方法来确定是否因为视图控制器被推到导航控制器的堆栈上,或者是否因为视图控制器因弹出而消失 .

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

12 回答

  • 226

    您可以使用以下内容 .

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

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

  • -1

    我认为最简单的方法是:

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

    迅速:

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

    来自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]) {
        }
    }
    

    Swift 3版本:

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

    如果您只是想知道您的视图是否被弹出,我刚刚发现 self.navigationControllerviewDidDisappear 中是 nil ,当它从控制器堆栈中删除时 . 所以这是一个简单的替代测试 .

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

  • 126

    斯威夫特4

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

    在Swift中:

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

    我发现Apple的文档很难理解 . 此扩展程序有助于查看每个导航的状态 .

    extension UIViewController {
        public func printTransitionStates() {
            print("isBeingPresented=\(isBeingPresented)")
            print("isBeingDismissed=\(isBeingDismissed)")
            print("isMovingToParentViewController=\(isMovingToParentViewController)")
            print("isMovingFromParentViewController=\(isMovingFromParentViewController)")
        }
    }
    
  • -1

    这个问题相当陈旧,但我偶然看到它,所以我想发布最佳实践(afaik)

    你可以这样做

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

    这适用于 iOS7 ,不知道它是否适用于任何其他的 . 据我所知,在 viewDidDisappear 中,视图已经被弹出 . 这意味着当您查询 self.navigationController.viewControllers 时,您将获得 nil . 所以,检查一下是否为零 .

    TL; DR

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

    在iOS 6中,Segues可以是一种非常有效的方法来处理这个问题 . 如果您在Interface Builder中为特定的segue指定了标识符,则可以在 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
        }
    }
    
  • 5

    我假设您的意思是当您说要推入堆栈时,通过推送新视图将视图移动到导航控制器的堆栈中 . 我建议使用 viewDidUnload 方法添加一个 NSLog 语句来向控制台写一些东西,这样你就可以看到发生了什么,你可能想要添加 NSLogviewWillDissappeer .

  • 9

    这是一个类别来完成与sbrocket的答案相同的事情:

    Header:

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

    Source:

    #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
    

相关问题