之前项目中遇到了,在这里记录下,网络找了很多,大部分写的不完成,基本不能实现。
第一种方法,很简单,重新签订协议:
首先,在要push的控制器中加入以下代码:
override func viewDidLoad() {
self.navigationController?.interactivePopGestureRecognizer?.delegate = self self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true } 并且遵守协议,然后既可以了。很简单。super.viewDidLoad()
还有一点记住,一般我们会将navigationController抽取成父类,如果是自定义的navigationController,也需要重新签订协议,否则还是没有返回手势,签订的方法如下:
override func viewDidLoad() { let selector = NSSelectorFromString("interactivePopGestureRecognizer") if self.responds(to: selector) { //重新签代理 self.interactivePopGestureRecognizer?.delegate = self } }
这样就可以了。
第二种方法就是利用runtime,而且这个方法可以替换系统的pop手势,这样就不会仅仅限制于在边缘滑动返回了,具体做法如下:
- 首先,我们已经知道系统是有一个左滑手势
- 该左滑手势只能在左边缘滑动才会生效
- 但是该手势的View&target&action系统已经创建好了
- 我们可以自己创建一个手势,但是利用系统的View&target&action
- 问题?
- 1> 如果获取系统手势的View?
- 比如简单,因为可以直接获取interactivePopGestureRecognizer手势
- interactivePopGestureRecognizer.view即可获得
- 2> 如果获取target&action
- 该方式较为麻烦,需要使用KVC
- 通过某一些Key来获取可接
- 3> 通过哪些key呢?
- 需要用运行时,遍历所有的属性找到
- 需要用运行时,遍历所有的属性找到
- 1> 如果获取系统手势的View?
- 代码分析:
class CustomNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// 1.取出手势&view
guard let gesture = interactivePopGestureRecognizer else { return }
gesture.isEnabled = false
let gestureView = gesture.view
// 2.获取所有的target
let target = (gesture.value(forKey: "_targets") as? [NSObject])?.first
guard let transition = target?.value(forKey: "_target") else { return }
let action = Selector(("handleNavigationTransition:"))
// 3.创建新的手势
let popGes = UIPanGestureRecognizer()
popGes.maximumNumberOfTouches = 1
gestureView?.addGestureRecognizer(popGes)
popGes.addTarget(transition, action: action)
}
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
viewController.hidesBottomBarWhenPushed = true
super.pushViewController(viewController, animated: animated)
}
}