viewWillDisappear:确定是否正在popup视图控制器或正在显示一个子视图控制器

我正在努力寻找这个问题的一个很好的解决scheme。 在视图控制器的-viewWillDisappear:方法中,我需要find一种方法来确定是因为视图控制器被推到导航控制器的堆栈上,还是因为视图控制器因为popup而消失。

目前我正在设置标志,如isShowingChildViewController但它变得相当复杂。 我想我可以检测到的唯一方法是在-dealloc方法。

您可以使用以下内容。

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

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

我认为最简单的方法是:

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

从UIViewController.h中的Apple文档:

“这四种方法可以用在视图控制器的外观callback中,以确定它是否作为子视图控制器被呈现,解散或添加或移除。例如,视图控制器可以检查它是否因为被解散而消失或者通过检查expression式([self isBeingDismissed] || [self isMovingFromParentViewController])在其viewWillDisappear:方法中自动popup。

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

所以是的,唯一logging的方式是这样的:

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

如果你只是想知道你的视图是否被popup,我刚刚发现self.navigationControllerviewDidDisappearnil的,当它从控制器堆栈中被移除时。 所以这是一个简单的替代testing。

(我尝试了各种其他的扭曲后发现,我很惊讶没有导航控制器协议来注册一个视图控制器来通知popup窗口,你不能使用UINavigationControllerDelegate因为这实际上是真正的显示工作。

在Swift中:

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

Swift 3

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

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

你可以做

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

这适用于iOS7 ,不知道是否适用于任何其他的。 据我所知,在viewDidDisappear视图已经被popup。 这意味着当你查询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"); } } 

在iOS 6+中,Segues可以成为处理这个问题的一种非常有效的方式。 如果你已经在Interface Builder中给出了一个特定的标识符,你可以在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 } } 

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

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

我假设你的意思是说你的视图正在被导入控制器的堆栈,通过推入一个新的视图,当你说推入堆栈。 我build议使用viewDidUnload方法添加一个NSLog语句来写入一些东西到控制台,所以你可以看到发生了什么,你可能想要添加一个NSLogviewWillDissappeer

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

标题:

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

资源:

 #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