从导航堆栈推送/弹出uiviewcontroller时如何收到警报

Posted

技术标签:

【中文标题】从导航堆栈推送/弹出uiviewcontroller时如何收到警报【英文标题】:How to be alerted when uiviewcontroller is pushed / popped from navigation stack 【发布时间】:2012-01-11 07:52:21 【问题描述】:

当我的视图控制器被推送或从导航堆栈中弹出时,我需要做某些事情,但我不想使用 viewillappear / viewdidappear 或 viewwilldisappear / viewdiddisappear,因为除了视图控制器被推送/弹出时,这些情况下.使用 navigationcontroller 委托和 navigationController:didShowViewController:animated: 和 navigationController:willShowViewController:animated: 的正确方法是吗?如果没有,最好的方法是什么?

【问题讨论】:

【参考方案1】:

要了解它何时被推送,您可以使用

UINavigationControllerDelegate

并实施

- (void)navigationController:(UINavigationController *)navigationController 
      willShowViewController:(UIViewController *)viewController
                    animated:(BOOL)animated

每当视图控制器被推入导航堆栈时,以及其顶部的视图控制器被弹出时,此方法都会触发,从而再次显示它。所以你必须使用一个标志来确定它是否已经被初始化,如果它还没有意味着它只是被推送。

要了解它何时被弹出,请使用以下答案:

viewWillDisappear: Determine whether view controller is being popped or is showing a sub-view controller

【讨论】:

【参考方案2】:

当对象从导航控制器堆栈中推送或弹出时,您可以尝试 UINavigationController 委托方法。

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

【讨论】:

【参考方案3】:

这是一个示例,用于检测何时通过覆盖 -viewWillAppear: 将视图控制器推入导航堆栈并通过覆盖 -viewWillDisappear: 弹出视图控制器

-(void) viewWillAppear:(BOOL)animated 
[super viewWillAppear:animated];
    if (self.isMovingToParentViewController) 
        NSLog(@"view controller being pushed");        
    


-(void) viewWillDisappear:(BOOL)animated 
[super viewWillDisappear:animated];
    if (self.isMovingFromParentViewController) 
        NSLog(@"view controller being popped");
    

【讨论】:

Overriding 是一个更好的词。【参考方案4】:

您始终可以创建 UINavigationController 的简单子类并包装其超类的方法,以便在调用它们之前设置一个标志:

ActionNavigationController.h

#import <UIKit/UIKit.h>

@interface ActionNavigationController : UINavigationController
@property (nonatomic, readonly) BOOL pushing;
@end

ActionNavigationController.m

#import "ActionNavigationController.h"

@implementation ActionNavigationController
@synthesize pushing = _pushing;

-(void)pushViewController:(UIViewController *)viewController 
                 animated:(BOOL)animated 
    _pushing = YES;
    [super pushViewController:viewController animated:animated];


- (UIViewController *)popViewControllerAnimated:(BOOL)animated 
    _pushing = NO;
    return [super popViewControllerAnimated:animated];

- (NSArray *)popToViewController:(UIViewController *)viewController 
                        animated:(BOOL)animated 
    _pushing = NO;
    return [super popToViewController:viewController animated:animated];

- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated 
    _pushing = NO;
    return [super popToRootViewControllerAnimated:animated];


@end

如果没有发生任何事情,pushing 将评估为 NO 事件,因此预计将从 UINavigationControllerDelegate 访问此代码。

【讨论】:

【参考方案5】:

谨慎使用

- (void)navigationController:(UINavigationController *)navigationController 
  willShowViewController:(UIViewController *)viewController
                animated:(BOOL)animated

如果用户从边缘向右滑动以弹出视图控制器(而不是实际弹出它),它将调用委托函数上方而不是函数下方

- (void)navigationController:(UINavigationController *)navigationController 
   didShowViewController:(UIViewController *)viewController 
                animated:(BOOL)animated;

请参考https://gist.github.com/nonamelive/9334458

【讨论】:

【参考方案6】:

你可以在 willShowViewController 中做类似的事情

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) 
    if self.navigationController!.viewControllers.contains(self)
        print ("push")
     else 
        print ("pop")
    

【讨论】:

【参考方案7】: (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController 动画:(BOOL)动画; (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController 动画:(BOOL)动画;

这些委托函数不会在 ios13 设备(使用 Xcode 11 编译)上调用。这是目前的错误吗?

【讨论】:

【参考方案8】:

将委托设置为导航控制器层次结构内的某些东西是不好的做法,而是观察通知:

UINavigationControllerWillShowViewControllerNotification

UINavigationControllerDidShowViewControllerNotification

并且 userInfo 对象包含“NextVisible”和“LastVisible”视图控制器。但是在外观方法中使用isMoving 可能是最好的方法。

【讨论】:

以上是关于从导航堆栈推送/弹出uiviewcontroller时如何收到警报的主要内容,如果未能解决你的问题,请参考以下文章

从弹出控制器推送视图控制器

推送导航控制器堆栈后视图不显示

如果导航堆栈中不存在视图控制器,则推送它

模态下的弹出/推送视图

iOS 简单视图从导航堆栈错误弹出

ios:如何关闭模态视图控制器,然后弹出推送的视图控制器