2009-11-29 96 views
121

我正在努力寻找解决此问题的良好解决方案。在视图控制器的-viewWillDisappear:方法中,我需要找到一种方法来确定是因为视图控制器被推到导航控制器的堆栈上,还是因为视图控制器因弹出而消失。viewWillDisappear:确定是否正在弹出视图控制器或正在显示子视图控制器

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

回答

219

您可以使用以下方法。

- (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被调用的时候进行更新。

+2

完美!我不知道为什么我没有想到这一点!我想我不认为堆栈会被调用,直到消失方法被调用!谢谢:-) – 2009-11-29 21:56:47

+1

我刚刚一直在尝试执行相同的事情,但在'viewWillAppear',它似乎是否视图控制器被推出或被推出的东西被揭示,viewControllers数组是相同的双向!有任何想法吗? – 2009-11-30 11:49:18

+0

我还应该注意到视图控制器在应用程序的整个生命周期中是持久的,所以我不能在'viewDidLoad'上执行我的操作,因为它只被调用一次!嗯,棘手的一个! – 2009-11-30 11:56:02

-1

我假设你的意思是说,当你说推入堆栈时,你的视图会通过推动一个新视图在导航控制器的栈中向下移动。我建议使用viewDidUnload方法添加一条NSLog语句来向控制台写入内容,以便您可以看到发生了什么,您可能需要将NSLog添加到viewWillDissappeer

16

如果你只是想知道你的视图是否被弹出,我刚刚发现self.navigationControllernilviewDidDisappear,当它从堆栈的控制器中删除。所以这是一个简单的替代测试。我很惊讶没有导航控制器协议来注册一个视图控制器来通知流行音乐,你不能使用UINavigationControllerDelegate,因为这实际上是真正的显示工作。 )

-1

这里是完成同样的事情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 
116

我认为最简单的方法是:

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

截至iOS 5这是答案,也许还检查isBeingDismissed – d370urn3ur 2013-12-23 10:52:13

+3

对于iOS7我必须再次检查[self.navigationController.viewControllers indexOfObject:self] == NSNotFound,因为背景应用程序也将通过此测试,但不会删除自己从导航堆栈。 – 2014-02-28 10:07:45

+0

整洁干净! – AsifHabib 2015-02-20 08:17:57

0

这个问题是很老,但我认为这是偶然,所以我要发布最佳实践(afaik)

你可以做

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

有很多降级答案,我认为公平地提一下为什么要降级答案。 – Jiraheta 2016-08-17 16:16:17

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+一个非常有效的方法。如果您在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

在夫特:

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

    super.viewWillDisappear(animated) 

} 
+0

确保使用as!而不是像 – dfmuir 2015-05-13 13:42:56

52

从苹果公司在UIViewController.h文档:

“这四种方法可以以视图控制器的外观用于 回调以确定它是否是被呈现,解散或添加 或作为子视图控制器被移除。例如,视图控制器 可以检查它是否正在消失b因为它被解雇或弹出 通过询问自己在其viewWillDisappear:方法通过检查 表达式([self isBeingDismissed] || [自 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);

所以,是的,唯一记载的方式来做到这一点是通过以下方式:

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

斯威夫特3版本:

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

    if self.isBeingDismissed || self.isMovingFromParentViewController { 
    } 
} 
+1

这是适当的答案。 – mattyohe 2015-11-24 16:26:08

3

斯威夫特3

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

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

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