InteractivePopGestureRecognizer causing app freezing
I had similar problem with freezing interface when using swipe-to-pop gesture.
In my case the problem was in controller1.viewDidAppear I was disabling swipe gesture: self.navigationController.interactivePopGestureRecognizer.enabled = NO
. So when user started to swipe back from contorller2, controller1.viewDidAppear was triggered and gesture was disabled, right during it's work.
I solved this by setting self.navigationController.interactivePopGestureRecognizer.delegate = self
in controller1 and implementing gestureRecognizerShouldBegin:
, instead of disabling gesture recognizer:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)] &&
gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
return NO;
}
return YES;
}
Swift 4:
Set the delegate,
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
Implement the delegate method,
extension YourVC: UIGestureRecognizerDelegate{
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer && conditionToDisableTheGesture {
return false
}else{
return true
}
}
}
I had problem when swipe back on first controller and then tap on tableViewCell, I think that force touch swipe from edge is registering swipe back before switches app, sometimes UI get stuck, sometimes when I swipe back it starts entering on destination controller. I solved problem with this extension, it worked for me and it is simple solution. Swift 4.2
extension UINavigationController:UINavigationControllerDelegate {
open override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
public func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
if responds(to: #selector(getter: self.interactivePopGestureRecognizer)) {
if viewControllers.count > 1 {
interactivePopGestureRecognizer?.isEnabled = true
} else {
interactivePopGestureRecognizer?.isEnabled = false
}
}
}
}
My solution was to add a delegate to the navigation controller. Then disable the pop gesture recogniser in the root view controller only. YMMV.
#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
BOOL isRootVC = viewController == navigationController.viewControllers.firstObject;
navigationController.interactivePopGestureRecognizer.enabled = !isRootVC;
}