牛骨文教育服务平台(让学习变的简单)

一:效果

第二篇里面写了怎样自定义navigation实现自定义的导航控制器左右按钮样式,但是当我们自己实现后,系统自带的向右边滑动来实现回退的功能就不能用了。

这里主要实现滑动回退功能 
。 

二:代码实现思路

首先 在 NYNavigationController.m中放一个popDelegate来放置要更改的手势代理对象

@interface NYNavigationController ()<UINavigationControllerDelegate>

@property (nonatomic, strong) id popDelegate;

@end

重写 UINavigationControllerDelegate 的方法- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated

viewDidLoad中设置代理方法,并且预先设置手势代理用来还原

- (void)viewDidLoad {
    [super viewDidLoad];

    //记住手势代理 用来还原
    _popDelegate = self.interactivePopGestureRecognizer.delegate;
    self.delegate = self;
}
//导航控制器跳转完成的控制器
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (viewController == self.viewControllers[0]) { // 是根控制器
        //还原手势代理
        self.interactivePopGestureRecognizer.delegate = _popDelegate;

    }else{ // 非根控制器
        //设置手势代理为空,就可以实现滑动了
        //实现滑动返回功能
        //清空滑动返回手势的代理,就能实现滑动返回功能了。
        self.interactivePopGestureRecognizer.delegate = nil;
    }
}

三: 全部navigationController的代码

内部包括设置左右按钮等等功能

//
//  NYNavigationController.m
//  猫猫微博
//
//  Created by apple on 15-7-29.
//  Copyright (c) 2015年 znycat. All rights reserved.
//

#import "NYNavigationController.h"
#import "UIBarButtonItem+Item.h"

@interface NYNavigationController ()<UINavigationControllerDelegate>

@property (nonatomic, strong) id popDelegate;

@end

@implementation NYNavigationController
+ (void)initialize
{
    // 获取当前类下面的UIBarButtonItem
    UIBarButtonItem *item = [UIBarButtonItem appearanceWhenContainedIn:self, nil];

    // 设置导航条按钮的文字颜色 为黄色
    NSMutableDictionary *titleAttr = [NSMutableDictionary dictionary];
    titleAttr[NSForegroundColorAttributeName] = [UIColor orangeColor];
    [item setTitleTextAttributes:titleAttr forState:UIControlStateNormal];

}

- (void)viewDidLoad {
    [super viewDidLoad];

    //记住手势代理 用来还原
    _popDelegate = self.interactivePopGestureRecognizer.delegate;
    self.delegate = self;
}

-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [super pushViewController:viewController animated:animated];

    // 设置非根控制器导航条内容
    if (self.viewControllers.count != 0) { //非根控制器
        //设置导航条的内容
        //设置导航条左边和右边
        //如果把导航条上的返回按钮覆盖了,那么就没有了滑动返回功能

        //设置左边按钮
        viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem barButtonItemWithImage:[UIImage imageNamed:@"navigationbar_back"] highImage:[UIImage imageNamed:@"navigationbar_back_highlighted"] target:self action:@selector(backToPre) forControlEvents:UIControlEventTouchUpInside];

        //设置右边按钮
        viewController.navigationItem.rightBarButtonItem = [UIBarButtonItem barButtonItemWithImage:[UIImage imageNamed:@"navigationbar_more"] highImage:[UIImage imageNamed:@"navigationbar_more_highlighted"] target:self action:@selector(backToRoot ) forControlEvents:UIControlEventTouchUpInside];

    }

}

-(void)backToPre{

    //返回上一个控制器
    [self popViewControllerAnimated:YES];

}

-(void)backToRoot{
    //返回根控制器
    [self popToRootViewControllerAnimated:YES];
}

#pragma mark - UINavigationControllerDelegate 实现滑动回退功能

//导航控制器跳转完成的控制器
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (viewController == self.viewControllers[0]) { // 是根控制器
        //还原手势代理
        self.interactivePopGestureRecognizer.delegate = _popDelegate;

    }else{ // 非根控制器
        //设置手势代理为空,就可以实现滑动了
        //实现滑动返回功能
        //清空滑动返回手势的代理,就能实现滑动返回功能了。
        self.interactivePopGestureRecognizer.delegate = nil;
    }
}

@end

四:注意

设置手势代理为空后必须要在该用的时候给设置回去,系统内部东西不能随便乱改,要么会出现难以预料的bug。在跟控制器的时候不小心做了回退滑动那样的操作会让再次进入下一个页面的导航控制器的右边按钮点击无效,app就崩溃了。

self.interactivePopGestureRecognizer.delegate = nil;