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.navigationController
在viewDidDisappear
是nil
的,当它从控制器堆栈中被移除时。 所以这是一个简单的替代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
语句来写入一些东西到控制台,所以你可以看到发生了什么,你可能想要添加一个NSLog
的viewWillDissappeer
。
这是一个类似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