仅供记录设置自定义返回按钮后,系统的手势滑动返回失效的解决办法
#import "JMCNavigationViewController.h"
#import <objc/runtime.h>
@interface JMCNavigationViewController () <UINavigationControllerDelegate, UIGestureRecognizerDelegate>
// 记录系统手势代理
@property (nonatomic, strong) id popGesture;
@end
@implementation JMCNavigationViewController
// 第一次初始化这个类调用,只调用一次
+ (void)initialize
{
if (self == [JMCNavigationViewController class]) {
// 获取导航条标识
UINavigationBar *bar = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[self]];
// 设置导航条的背景图片,只能使用默认模式
[bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:(UIBarMetricsDefault)];
// 设置导航字体颜色大小
NSMutableDictionary *dictM = [NSMutableDictionary dictionary];
// 字体大小
dictM[NSFontAttributeName] = [UIFont boldSystemFontOfSize:22];
// 字体颜色
dictM[NSForegroundColorAttributeName] = [UIColor whiteColor];
[bar setTitleTextAttributes: dictM];
// // 另一种方式实现不带标题的返回按钮(不好使)
// // 设置颜色
// [bar setTintColor:[UIColor whiteColor]];
// // 获取当前导航栏的item
// UIBarButtonItem *item = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[self]];
// // 把返回标题移除到屏幕外面
// [item setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -100) forBarMetrics:UIBarMetricsDefault];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// 恢复系统的滑动返回手势
// 记录系统滑动手势代理
self.popGesture = self.interactivePopGestureRecognizer.delegate;
// 设置navigation代理
self.delegate = self;
// 全屏滑动移除控制器(系统默认是屏幕左侧滑动可以返回)
UIScreenEdgePanGestureRecognizer *panS = self.interactivePopGestureRecognizer;
// 打印私有属性
// runtime 运行机制,只能获取当前类的私有属性
// unsigned int outCount = 0;
// Ivar *ivars = class_copyIvarList([UIGestureRecognizer class], &outCount);
// for (int i = 0 ; i < outCount; i++) {
// NSLog(@"%@",[NSString stringWithUTF8String:ivar_getName(ivars[i])]);
// }
// 获取私有属性
NSArray *targets = [panS valueForKey:@"_targets"];
id target = [targets[0] valueForKey:@"target"];
// 添加自己的手势到系统
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
[self.view addGestureRecognizer:pan];
// 添加代理,屏蔽根控制器禁止滑动,如果在根控制器滑动会卡死
pan.delegate = self;
}
#pragma mark - UIGestureRecognizerDelegate 手势代理方法
// 开始滑动的时候会调用,返回YES 可以滑动,返回NO 不能滑动
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
// 如果大于1个控制器,就说明不是在根控制器,就返回YES
return self.viewControllers.count > 1;
}
#pragma mark - UINavigationControllerDelegate 导航条代理方法
// 获取当前显示的控制器
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// 判断第一个是不是根控制器
if (self.viewControllers[0] == viewController) {
// 还原系统手势代理
self.interactivePopGestureRecognizer.delegate = self.popGesture;
} else
{
// 因为设置了返回键,清空系统手势代理,就能实现滑动
self.interactivePopGestureRecognizer.delegate = nil;
}
}
// 统一设置非根控制器的返回键
#pragma mark - 重写方法,统一设置返回键
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[super pushViewController:viewController animated:animated];
// 设置非根控制器返回键
// 如果在导航控制器设置统一返回按钮,就没有手势返回功能了
if (self.viewControllers.count > 1) {
// imageWithRenderOriginalName 分类中自定义的不渲染图片的方法
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageWithRenderOriginalName:@"NavBack"] style:0 target:self action:@selector(backClick)];
}
}
- (void)backClick {
[self popViewControllerAnimated:YES];
}
@end
网友评论