iOS让导航返回按钮可以选择性的pop

需求是从不同页面push过来要做不同的pop,有的直接返回上一级,有的要返回到rootViewController。

介绍我想到的有两种方式和遇到的问题以及解决的办法。


方式一:

自定义一个按钮,添加点击事件,在事件中去自由的pop,然后把这个自定义按钮设置为导航栏的self.navigationItem.leftBarButtonItem。

存在的问题:左滑返回的手势失效了。

解决办法:
第一步:在RootViewController的viewDidAppear中把self.navigationController.interactivePopGestureRecognizer.enabled = NO;

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    // 解决自定义返回按钮影响左滑手势的问题
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}

第二步:
在push控制器前调用

    // 解决自定义返回按钮影响左滑手势的问题
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
    {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
        self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    }

方式二:

但是我的项目中用的都是系统的返回按钮,如果自定义的话样式会不统一,所以要用系统的返回按钮。

存在的问题:怎么拦截导航栏返回按钮事件

解决办法
声明:此方法网上流传已久,我只是搬运工,记录下来。具体的作者我也不知道是谁,向作者致敬。@此方法的第一位分享者
可能是http://stackoverflow.com/questions/1214965/setting-action-for-back-button-in-navigation-controller/19132881#19132881

可以为 UINavigatonController 创建一个 Category,来定制navigationBar: shouldPopItem: 的逻辑。这里需要注意的是,我们不需要去设置 delegate,因为 UINavigatonController 自带的 UINavigationBar 的 delegate 就是导航栏本身。这样还有个问题就是,那在实际的 Controller 里面怎么控制呢?因此同样需要对 UIViewController 添加一个 Protocol,这样在 Controller 中使用该 Protocol 提供的方法即可进行控制了,代码如下
.h中:

@protocol BackButtonHandlerProtocol 
@optional
// 重写下面的方法以拦截导航栏返回按钮点击事件,返回 YES 则 pop,NO 则不 pop
-(BOOL)navigationShouldPopOnBackButton;
@end

@interface UIViewController (BackButtonHandler) 

@end

.m中

@implementation UIViewController (BackButtonHandler)

@end


@implementation UINavigationController (ShouldPopOnBackButton)

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
    
    if([self.viewControllers count] < [navigationBar.items count]) {
        return YES;
    }
    
    BOOL shouldPop = YES;
    UIViewController* vc = [self topViewController];
    if([vc respondsToSelector:@selector(navigationShouldPopOnBackButton)]) {
        shouldPop = [vc navigationShouldPopOnBackButton];
    }
    
    if(shouldPop) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self popViewControllerAnimated:YES];
        });
    } else {
        // 取消 pop 后,复原返回按钮的状态
        for(UIView *subview in [navigationBar subviews]) {
            if(0. < subview.alpha && subview.alpha < 1.) {
                [UIView animateWithDuration:.25 animations:^{
                    subview.alpha = 1.;
                }];
            }
        }
    }
    return NO;
}

@end

调用:
在需要定制的ViewController中导入分类

#import "UIViewController+BackButtonHandler.h"

重写navigationShouldPopOnBackButton方法:

- (void)navigationShouldPopOnBackButton {
    // 定制具体的pop方式
    if ([self.inputParameter[@"isAgreementPage"] boolValue]) {
        [self.navigationController popToRootViewControllerAnimated:YES];
    } else {
        [self.navigationController popViewControllerAnimated:YES];
    }
}

@end

你可能感兴趣的:(iOS让导航返回按钮可以选择性的pop)