iOS 拦截导航的pop事件

来源:互联网 发布:淘宝网店服装模特招聘 编辑:程序博客网 时间:2024/06/11 02:32

iOS拦截导航栏返回按钮事件的正确方式

一、为 UINavigationController 添加 category

此方法来自 github:UIViewController-BackButtonHandler

由于系统的 UINavigationController 使用了一个 UINavigationBar 来管理 Controller 的 pop 和 push 等操作,所以仔细查看UINavigationBar 的 API,会发现一个 UINavigationBarDelegate,它包含了四个方法:

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item; // called to push. return NO not to.- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item;    // called at end of animation of push or immediately if not animated- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;  // same as push methods- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;

我们会惊喜的第一个不就是我们想要的效果吗?因为该方法返回 YES 则 pop,若返回NO,则不POP。

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

// UIViewController+BackButtonHandler.h@protocol BackButtonHandlerProtocol <NSObject>@optional// 重写下面的方法以拦截导航栏返回按钮点击事件,返回 YES 则 pop,NO 则不 pop-(BOOL)navigationShouldPopOnBackButton;@end@interface UIViewController (BackButtonHandler) <BackButtonHandlerProtocol>@end
// UIViewController+BackButtonHandler.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;}

使用方法:

(1). 在控制器中导入头文件:

#import "UIViewController+BackButtonHandler.h"

(2). 重写 navigationShouldPopOnBackButton 方法

- (BOOL)navigationShouldPopOnBackButton{    [[[UIAlertView alloc] initWithTitle:@"提示" message:@"确定返回上一界面?"                               delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil] show];    return NO;}// UIAlertViewDelegate- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex{    if (buttonIndex==1) {        [self.navigationController popViewControllerAnimated:YES];    }}
阅读全文
0 0
原创粉丝点击