【问题标题】:InteractivePopGestureRecognizer causing app freezingInteractivePopGestureRecognizer 导致应用程序冻结
【发布时间】:2014-01-19 19:33:47
【问题描述】:

在我的应用中,我有不同的控制器。当我将控制器 1 推到导航控制器并向后滑动时,一切正常。但是,如果我推导航控制器 1,然后进入控制器 1 推控制器 2 并尝试向后滑动,我会得到一个冻结的应用程序。如果通过返回按钮返回一切正常。

我怎样才能发现问题?

【问题讨论】:

  • 当它冻结时,如果您使用调试器暂停应用程序会显示什么?任何日志/异常?
  • 您的问题很可能在于弹出 VC 的 viewWillDisappear 和/或您要弹出的 VC 的 viewWillAppear。如果可能的话,分享一些代码。

标签: ios objective-c interactivepopgesture


【解决方案1】:

我在使用滑动弹出手势时遇到了类似的冻结界面问题。 就我而言,问题出在 controller1.viewDidAppear 我禁用了滑动手势:self.navigationController.interactivePopGestureRecognizer.enabled = NO。因此,当用户开始从 contorller2 向后滑动时,controller1.viewDidAppear 被触发并且手势被禁用,就在它工作期间。

我通过在控制器 1 中设置 self.navigationController.interactivePopGestureRecognizer.delegate = self 并实现 gestureRecognizerShouldBegin: 解决了这个问题,而不是禁用手势识别器:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)] &&
            gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
        return NO;
    }
    return YES;
}

【讨论】:

  • 我做了类似的解决方案 - 在 vi​​ewWillAppear 中将标志设置为 False,在 viewDidAppear 中将标志设置为 True。在gestureRecognizerShouldBegin 中,我在True 上检查此值以启用手势。您的解决方案看起来更优雅,我会尝试这样做并会说结果。感谢回复
  • 如果你没有在controller2中设置self.navigationController.interactivePopGestureRecognizer.delegate = self,controller1会在推送controller2之后得到委托调用。
  • 我继承 UINavigationController 并实现它的委托来启用/禁用识别器:stackoverflow.com/a/41619830/954643
【解决方案2】:

我的解决方案是向导航控制器添加一个委托。然后仅在根视图控制器中禁用弹出手势识别器。 YMMV。

#pragma mark - UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    BOOL isRootVC = viewController == navigationController.viewControllers.firstObject;
    navigationController.interactivePopGestureRecognizer.enabled = !isRootVC;
}

【讨论】:

  • 我花了好几个小时来研究为什么应用程序挂起,您先生太棒了,感谢您提供最优雅的答案!修复了挂起。一旦我推送了一个成为交互式 vc 代表的 VC,当我回到根 vc 并从左边缘滑动然后再次推送一个 vc 时,每次都会挂起,这解决了它!
  • 这不起作用,因为在动画发生期间滑动时仍然会导致冻结。
  • 如果您希望任何子 VC 禁用滑动导航,则不起作用。
【解决方案3】:

我在第一个控制器上滑动然后点击 tableViewCell 时遇到问题,我认为从边缘强制触摸滑动是在切换应用程序之前注册滑动,有时 UI 卡住,有时当我向后滑动时它开始进入目标控制器.我解决了这个扩展的问题,它对我有用,而且是简单的解决方案。斯威夫特 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
            }
        }
    }
}

【讨论】:

    【解决方案4】:

    斯威夫特 4:

    设置委托,

    self.navigationController?.interactivePopGestureRecognizer?.delegate = self
    

    实现委托方法,

    extension YourVC: UIGestureRecognizerDelegate{
        func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
            if gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer && conditionToDisableTheGesture {
                return false
            }else{
                return true
            }
        }
    
    }
    

    【讨论】:

    • 您的条件语句中的conditionToDisableTheGesture 是什么意思?
    • @Alena conditionToDisableTheGesture 表示在什么条件下(如果有),您要禁用此手势。就我而言,我只需要针对特定​​场景禁用此手势。
    【解决方案5】:

    我遇到了同样的问题,我找到了以下解决方案。在控制器下面添加

    #import <UIKit/UIKit.h>
    @interface CBNavigationController : UINavigationController     <UIGestureRecognizerDelegate,UINavigationControllerDelegate>
    @end
    
    #import "CBNavigationController.h"
    @interface CBNavigationController ()
    @end
    @implementation CBNavigationController
    - (void)viewDidLoad
    {
    NSLog(@"%s",__FUNCTION__);
    __weak CBNavigationController *weakSelf = self;
    
    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
    {
        self.interactivePopGestureRecognizer.delegate = weakSelf;
        self.delegate = weakSelf;
    }
    }
    
    - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
    NSLog(@"%s",__FUNCTION__);
    
    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
        self.interactivePopGestureRecognizer.enabled = NO;
    
    [super pushViewController:viewController animated:animated];
    }
    
    #pragma mark UINavigationControllerDelegate
    - (void)navigationController:(UINavigationController *)navigationController
       didShowViewController:(UIViewController *)viewController
                    animated:(BOOL)animate
    {
    NSLog(@"%s",__FUNCTION__);
    
    // Enable the gesture again once the new controller is shown
    
    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
        self.interactivePopGestureRecognizer.enabled = YES;
    }
    @end
    

    可以参考以下链接

    http://keighl.com/post/ios7-interactive-pop-gesture-custom-back-button/

    【讨论】:

      【解决方案6】:

      我的解决方案是在selfImplementDelegate 和SystemDelegate 之间交换self.navigationController.interactivePopGestureRecognizer.delegate

      - (void)viewWillAppear:(BOOL)animated{
          [super viewWillAppear:animated];
          [_tableView reloadData];
          _oldReturnDelegate = self.navigationController.interactivePopGestureRecognizer.delegate;
          self.navigationController.interactivePopGestureRecognizer.delegate = self;
      }
      
      - (void)viewWillDisappear:(BOOL)animated
      {
          self.navigationController.interactivePopGestureRecognizer.delegate = _oldReturnDelegate;
          [super viewWillDisappear:animated];
      }
      

      【讨论】:

      • 这其实是这个问题的正确根源。用户设置的委托覆盖系统的默认导航委托。设置回 nil 是不够的。但由于令人讨厌的全局状态,我不会在生产中使用此解决方案。
      【解决方案7】:

      我建议你试试这个。这对我来说非常有效。您仍然可以享受交互式滑动。

      - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
        if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)] &&
            gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
          if(self.navigationController.viewControllers.count<=1)
          {
            return NO;
          }
        }
        return YES;
      }
      

      【讨论】:

        【解决方案8】:

        斯威夫特 4

        将此代码添加到根导航控制器

        func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
            return self == self.navigationController?.topViewController ? false : true
        }
        

        添加 UIGestureRecognizerDelegate 协议

        self.navigationController?.interactivePopGestureRecognizer?.delegate = self
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
        

        【讨论】:

          【解决方案9】:

          我通过UINavigationController interactivePopGestureRecognizer working abnormal in iOS7 解决了我的问题并设置self.navigationController.interactivePopGestureRecognizer.delegate = self; 在每个视图控制器上 - (void)viewWillAppear:(BOOL)animated

          【讨论】:

            猜你喜欢
            • 2015-08-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-22
            • 2017-09-16
            • 2019-03-17
            相关资源
            最近更新 更多