iOS:优雅的拦截返回按钮

背景:有时候我们会遇到需要在用户点击返回按钮pop之前进行拦截,增加一些业务逻辑,如弹出警告弹框询问用户是否确实要返回等。

实现代码
  • 1、创建一个协议MZCustomProtocol
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@protocol MZCustomProtocol <NSObject>

@optional
/// 点击返回按钮的时候, 需要增加额外操作的时候, 在当前控制器里实现该方法
- (void)onClickBackButtonWithAdditionalOperating:(UIBarButtonItem *)backItem;

@end

NS_ASSUME_NONNULL_END
  • 2、自定义导航控制器MZBaseNavVC
#import "MZBaseNavVC.h"

#import "MZCustomProtocol.h"

@interface MZBaseNavVC ()<UIGestureRecognizerDelegate>
@end

@implementation MZBaseNavVC

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.interactivePopGestureRecognizer.delegate = self;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    // 实现了指定方法的控制器, 就不允许侧滑返回
    if ([self.viewControllers.lastObject respondsToSelector:@selector(onClickBackButtonWithAdditionalOperating:)]) {
        return NO;;
    }
    return self.childViewControllers.count > 1;
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.childViewControllers.count > 0) {
        UIButton *back = [UIButton buttonWithType:UIButtonTypeCustom];
        back.frame = CGRectMake(0, 0, 44, 44);
        [back setImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal];
        [back addTarget:self action:@selector(onClickBackButton:) forControlEvents:UIControlEventTouchUpInside];
        UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithCustomView:back];
        viewController.navigationItem.leftBarButtonItem = backItem;
        self.hidesBottomBarWhenPushed = YES;
    }
    
    [super pushViewController:viewController animated:animated];
}

- (void)onClickBackButton:(id)sender {
    // 实现了指定方法的控制器, 就走当前控制器里实现的方法
    if ([self.viewControllers.lastObject respondsToSelector:@selector(onClickBackButtonWithAdditionalOperating:)]) {
        [(id<MZCustomProtocol>)self.viewControllers.lastObject onClickBackButtonWithAdditionalOperating:sender];
    } else {
        // If the view controller at the top of the stack is the root view controller, this method does nothing.
        [self.navigationController popViewControllerAnimated:YES];
    }
}

@end
  • 3、在需要拦截返回按钮的控制器里,实现对应的方法 onClickBackButtonWithAdditionalOperating:
#import "DetailViewController.h"

#import "MZCustomProtocol.h"

@interface DetailViewController ()<MZCustomProtocol>
@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
}

- (void)onClickBackButtonWithAdditionalOperating:(UIBarButtonItem *)backItem {
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"返回后数据将不保存" preferredStyle:UIAlertControllerStyleAlert];
    __weak typeof(self) weakSelf = self;
    [alertVC addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil]];
     [alertVC addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
         [weakSelf.navigationController popViewControllerAnimated:YES];
    }]];
    [self presentViewController:alertVC animated:YES completion:nil];
}

@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容