[英]interactivePopGestureRecognizer corrupts navigation stack on root view controller
In my UINavigationController
I added custom back buttons with the side effect that it is not possible anymore to swipe left to right to pop the view controller and navigate back.在我的
UINavigationController
中,我添加了自定义后退按钮,其副作用是无法再从左向右滑动以弹出视图控制器并向后导航。
So I implemented interactivePopGestureRecognizer
in my custom UINavigationController
class:所以我在我的自定义
UINavigationController
类中实现了interactivePopGestureRecognizer
:
class UINavigationControllerExtended: UINavigationController, UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
if self.respondsToSelector(Selector("interactivePopGestureRecognizer")) {
self.interactivePopGestureRecognizer?.delegate = self
}
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailByGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return gestureRecognizer.isKindOfClass(UIScreenEdgePanGestureRecognizer)
}
}
This works fine except when I am in my root view controller (RVC) which is a UICollectionViewController
, ie the most bottom view controller in the navigation stack.这工作正常,除非我在我的根视图控制器 (RVC) 中,它是一个
UICollectionViewController
,即导航堆栈中最底部的视图控制器。 When I do the swipe left to right gesture, nothing seems to happen, as expected.当我做从左向右滑动的手势时,似乎没有发生任何事情,正如预期的那样。 But when I then tap a UICollectionViewCell the destination view controller (DVC) does not get pushed over the RVC.
但是,当我随后点击 UICollectionViewCell 时,目标视图控制器 (DVC) 不会被推到 RVC 上。 Instead I only see the DVC's shadow on the right side of the screen.
相反,我只在屏幕右侧看到 DVC 的影子。
The RVC is not responsive anymore, but as I swipe left to right again, the DVC interactively moves right to left into the screen. RVC 不再响应,但当我再次从左向右滑动时,DVC 交互地从右向左移动到屏幕中。 When I finish the gesture, the DVC moves completely into the screen just to quickly disappear left to right again.
当我完成手势时,DVC 完全移入屏幕,然后再次从左到右快速消失。 The RVC becomes responsive again.
RVC 再次响应。
So it seems the DVC gets pushed onto the navigation stack but not visibly into the screen.所以看起来 DVC 被推到导航堆栈上但没有明显地进入屏幕。
Any suggestions where this strange behaviour originates?这种奇怪行为的起源有什么建议吗?
Implement UINavigationControllerDelegate
for your navigation controller and enable/disable the gesture recognizer there.为您的导航控制器实施
UINavigationControllerDelegate
并在那里启用/禁用手势识别器。
// Fix bug when pop gesture is enabled for the root controller
func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
self.interactivePopGestureRecognizer?.enabled = self.viewControllers.count > 1
}
Keeping the code independent from the pushed view controllers.保持代码独立于推送的视图控制器。
My current solution is to disable the interactivePopGestureRecognizer
in the root view controller:我当前的解决方案是在根视图控制器中禁用
interactivePopGestureRecognizer
:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.interactivePopGestureRecognizer?.enabled = false
}
In the first child view controller I enable it again.在第一个子视图控制器中,我再次启用它。 But this seems to be more a workaround because I don't understand the actual problem why the navigation stack got messed up in the first place.
但这似乎更像是一种解决方法,因为我不明白为什么导航堆栈一开始就搞砸了的实际问题。
Here is my solution for this.这是我的解决方案。 Swift 4.2
斯威夫特 4.2
Implement UIGestureRecognizerDelegate
and UINavigationControllerDelegate
protocols.实施
UIGestureRecognizerDelegate
和UINavigationControllerDelegate
协议。 In my case I did this in an UITabBarController
that would be also my root view controller.在我的例子中,我在
UITabBarController
中执行了此操作,它也是我的根视图控制器。
Then, on viewDidLoad, do:然后,在 viewDidLoad 上执行:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
self.navigationController?.delegate = self
}
Then, add the delegate method for UINavigationControllerDelegate
and check if it is the root view by counting the number of view on the navigation controller and disable it if it is or enable it if its not.然后,为
UINavigationControllerDelegate
添加委托方法,并通过计算导航控制器上的视图数量来检查它是否是根视图,如果是则禁用它,如果不是则启用它。
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
let enable = self.navigationController?.viewControllers.count ?? 0 > 1
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = enable
}
Lastly, add the UIGestureRecognizerDelegate
method最后,添加
UIGestureRecognizerDelegate
方法
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
This should fix the problem without the necessity of manually enabling/disabling the gesture recogniser in every view of your project.这应该可以解决问题,而无需在项目的每个视图中手动启用/禁用手势识别器。
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
self.interactivePopGestureRecognizer?.isEnabled = self.viewControllers.count > 1
}
Updated @rivera solution for Swift 5更新了 Swift 5 的@rivera 解决方案
Solution from Guilherme Carvalho worked for me, but I had to assign delegate methods in viewWillAppear
, in viewDidLoad
was too late for my implementation. Guilherme Carvalho的解决方案对我有用,但我必须在
viewWillAppear
中分配委托方法,在viewDidLoad
中对我的实现来说为时已晚。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.interactivePopGestureRecognizer?.delegate = self
navigationController?.delegate = self
}
Try this code试试这个代码
func navigationController(navigationController: UINavigationController, didShowViewController vc: UIViewController, animated: Bool) {
self.interactivePopGestureRecognizer?.enabled = self.vc.count > 1
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.