欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

iOS 点击左上角返回按钮Pop到指定控制器

程序员文章站 2022-03-03 22:30:43
...

因为项目需求,需要解决两个功能点:1.击每个页面的左上角的返回按钮,除了返回上一级页面之外,还需要Pop到根控制器,甚至是指定控制器(因为默认是返回上一级,所以在这里只列举其他两种情况!)。2.关闭系统默认屏边滑动返回功能

1. 自定义QDNavigationController类

因为我自定义了继承自UINavigationController 的类QDNavigationController,并且重写了系统UINavigationController的代理UINavigationControllerDelegate的方法:- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated以控制每个页面的的屏边手势滑动返回功能,在我自定义的QDNavigationController.h类头文件中添加了代码如下:

1.1 QDNavigationController.h

typedef NS_OPTIONS(NSInteger, QDVCType){
    QDVCTypePreVC,
    QDVCTypeRootVC,
    QDVCTypeTargetVC,
};

@interface QDNavigationController : UINavigationController

@property (nonatomic, strong) id popDelegate;

@property (nonatomic, assign) QDVCType type;

@property (nonatomic, strong) UIViewController *targetVC;

@end

1.2 QDNavigationController.m

QDNavigationController.m实现文件如下:

//导航控制器跳转完成时候的调用
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if (viewController == self.viewControllers[0]) {//显示根控制器
        self.interactivePopGestureRecognizer.delegate = _popDelegate;
        
    }else{//不是显示根控制器
        self.interactivePopGestureRecognizer.delegate = nil;//清空滑动返回手势的代理,就能实现滑动功能
        
    }
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    
    if (self.childViewControllers.count) { //不是根控制器
        
        viewController.hidesBottomBarWhenPushed = YES;
        
        UIBarButtonItem *left = [UIBarButtonItem barButtonItemWithImage:[UIImage imageNamed:@"icon_back_topbar"] highImage:[UIImage imageNamed:@"icon_back_topbar"] title:nil target:self action:@selector(popToPre) forControlEvents:UIControlEventTouchUpInside];
        // 设置导航条的按钮
        viewController.navigationItem.leftBarButtonItem = left;
    }
    return [super pushViewController:viewController animated:animated];
}

- (void)popToPre{
    
    switch (self.type) {
        case QDVCTypePreVC:
            [self popViewControllerAnimated:YES];
            break;
        case QDVCTypeRootVC:
            [self popToRootViewControllerAnimated:YES];
            break;
        case QDVCTypeTargetVC:
            [self popToAppointVC:self.targetVC];
            break;
        default:
            break;
    }
}

2. 返回到根控制

现在在实现自定义Pop并且禁掉手势的页面导入#import "QDNavigationController.h" 头文件,接着代码实现如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationController.delegate = self;//让当前控制器成为导航的代码
}

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    
    QDNavigationController *naviVC = (QDNavigationController *)navigationController;
    if (viewController == navigationController.viewControllers[0]) {
        //1.显示根控制器,不能滑动
        naviVC.interactivePopGestureRecognizer.delegate = naviVC.popDelegate;//1.1.禁掉手机屏边收拾返回滑动功能
        naviVC.type = QDVCTypePreVC;//1.2.恢复返回的类型
    }else{
        //2.不是显示根控制器,清空滑动返回手势的代理,就能实现滑动功能
        if ([viewController isKindOfClass:[QDForgetController class]]) {
            naviVC.interactivePopGestureRecognizer.delegate = naviVC.popDelegate;//2.1.禁掉手机屏边收拾返回滑动功能
            naviVC.type = QDVCTypeRootVC;//2.2.指定返回的类型
        }else{
            naviVC.interactivePopGestureRecognizer.delegate = nil;//2.4.恢复手机屏边收拾返回滑动功能
            naviVC.type = QDVCTypePreVC;//2.5.恢复返回的类型
        }
    }

//3.解决与父视图重叠问题
    //3.1.获取主主窗口
    UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
    UITabBarController *tabBarVC = (UITabBarController *) keyWindow.rootViewController;
    //3.2.移除系统tabBarButton
    for (UIView *tabBarButton in tabBarVC.tabBar.subviews) {
        if ([tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
            [tabBarButton removeFromSuperview];
        }
    }
}

3. 返回到根指定控制器

同样需要遵守系统UINavigationController的代理UINavigationControllerDelegate,导入#import "QDNavigationController.h"头文件,和返回根控制器不同的是需要指定一个控制器对象,接着直接代码实现如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationController.delegate = self;//让当前控制器成为导航的代码
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    
    QDNavigationController *naviVC = (QDNavigationController *)navigationController;
    if (viewController == navigationController.viewControllers[0]) {
        //1.显示根控制器,不能滑动
        naviVC.interactivePopGestureRecognizer.delegate = naviVC.popDelegate;//1.1.禁掉手机屏边收拾返回滑动功能
        naviVC.type = QDVCTypePreVC;//1.2.恢复返回的类型
        naviVC.targetVC = nil;//1.3.清空跳转指定控制器
    }else{
        //2.不是显示根控制器,清空滑动返回手势的代理,就能实现滑动功能
        if ([viewController isKindOfClass:[QDForgetController class]]) {
            naviVC.interactivePopGestureRecognizer.delegate = naviVC.popDelegate;//2.1.禁掉手机屏边收拾返回滑动功能
            naviVC.type = QDVCTypeTargetVC;//2.2.指定返回的类型
            naviVC.targetVC = [[QDLoginController alloc] init];//2.3.设置要跳转的指定控制器
        }else{
            naviVC.interactivePopGestureRecognizer.delegate = nil;//2.4.恢复手机屏边收拾返回滑动功能
            naviVC.type = QDVCTypePreVC;//2.5.恢复返回的类型
            naviVC.targetVC = nil;//2.6.清空跳转指定控制器
        }
    }
//解决跳转问题
    QDNavigationController *naviVC = (QDNavigationController *)navigationController;
    if (viewController == navigationController.viewControllers[0]) {
        //1.显示根控制器,不能滑动
        //1.1.禁掉手机屏边收拾返回滑动功能
        naviVC.interactivePopGestureRecognizer.delegate = naviVC.popDelegate;
        //1.2.恢复返回的类型
        naviVC.type = QDVCTypePreVC;
    }else{
        //2.不是显示根控制器,清空滑动返回手势的代理,就能实现滑动功能
        if ([viewController isKindOfClass:[self class]]) {
            naviVC.interactivePopGestureRecognizer.delegate = naviVC.popDelegate;//2.1.禁掉手机屏边收拾返回滑动功能
            naviVC.type = QDVCTypeRootVC;//2.2.指定返回的类型
        }else{
            naviVC.interactivePopGestureRecognizer.delegate = nil;//2.4.恢复手机屏边收拾返回滑动功能
            naviVC.type = QDVCTypePreVC;//2.5.恢复返回的类型
        }
    }
    
    //3.解决与父视图重叠问题
    //3.1.获取主主窗口
    UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
    UITabBarController *tabBarVC = (UITabBarController *) keyWindow.rootViewController;
    //3.2.移除系统tabBarButton
    for (UIView *tabBarButton in tabBarVC.tabBar.subviews) {
        if ([tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
            [tabBarButton removeFromSuperview];
        }
    }
}