【问题标题】:Disable swipe back gesture in Swift在 Swift 中禁用向后滑动手势
【发布时间】:2015-10-22 06:45:38
【问题描述】:

在这里找了一段时间,但似乎找不到有效的解决方案。

我正在尝试在 Swift 中禁用滑动以返回上一个视图手势。

我尝试了多种解决方案,包括:

self.navigationController?.interactivePopGestureRecognizer.enabled = false

self.navigationController.interactivePopGestureRecognizer.delegate = self

func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer!) -> Bool {
    return false
}

有没有一种新方法可以做到这一点或其他一些有效的方法?

【问题讨论】:

  • 当用户没有完全滑动时会导致问题,并干扰我们正在使用的 UI 的性质(在音轨中寻找时间)
  • 好吧,我不想打断你的问题,但我建议你 (1) 解决不完全滑动的问题和 (2) 缩进你的音轨搜索 UI,这样就不会如此接近边缘。这是预期的 UX,对于 iPhone 6 Plus 和 iPad 用户来说尤其重要,因为他们很难进入导航栏。
  • 无论如何,您的代码应该禁用手势识别器。它适用于旧版本的 iOS 吗?
  • 关于 iPhone 6 的好点 - 也许我会考虑修改 dealloc 方法 - 但我仍然会留下这个问题,因为我仍然感兴趣
  • 我至少在 iOS 8 上进行测试

标签: ios swift uinavigationcontroller


【解决方案1】:

以下是禁用和重新启用向后滑动的简单方法。

Swift 3.x 及以上版本

在 viewDidLoad/willAppear/didAppear 方法中添加:

navigationController?.interactivePopGestureRecognizer?.isEnabled = false

请记住,如果您使用viewDidLoad 执行此操作,则下次打开视图时,可能不会根据它是否保留在您的堆栈中进行设置。

除非您希望它保持关闭状态,否则您需要在通过willMove(toParentViewController:)willDisappear 关闭视图时重新打开它。你的navigationController 将在viewDidDisappear 处为零,所以为时已晚。

navigationController?.interactivePopGestureRecognizer?.isEnabled = true

关于SplitViewControllers的特别说明:

正如 CompC 在 cmets 中指出的那样,您需要调用第二个导航控制器以将其应用于详细视图:

navigationController?.navigationController?.interactivePopGe‌​stureRecognizer?.isE‌​nabled = false

Swift 2.2 和 Objective-C

Swift 2.x 及以下版本:

navigationController?.interactivePopGestureRecognizer?.enabled

目标-C:

self.navigationController.interactivePopGestureRecognizer.enabled

【讨论】:

  • 我在让它工作时遇到了一些麻烦,直到我意识到由于我试图禁用它的视图控制器位于拆分视图控制器的细节端,它在技术上处于单独的导航控制器(即使折叠时,它看起来像是在同一个控制器中)。为了解决这个问题,我必须这样做:navigationController?.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
  • @CompC 感谢您的更新,从未遇到过这种情况,很高兴知道。
  • 在 didAppear 中禁用它就足够了,然后在 willDisappear 中重新启用它。特别是在 didDisappear 上重新启用它是没有用的,因为 navigationController 属性已经为零。
  • 谢谢,这应该是正确的答案
  • @iajmeri43 可以,创建UINavigationController的子类,然后在它的viewDidLoad中设置属性。只要应用程序中您想要的所有视图都使用导航控制器,它就会工作。
【解决方案2】:

您可以禁用它,但不建议这样做,因为大多数 iOS 用户通过滑动返回而不是按返回按钮。 如果你想禁用它,使用modal segue 代替推送segue 会更合理,因为它不是那么大的转移。 如果你真的想摆脱滑动返回功能,我会禁用返回按钮并在屏幕右上角有一个完成按钮。

self.navigationController?.navigationItem.backBarButtonItem?.isEnabled = false;

【讨论】:

    【解决方案3】:

    我可以通过在gestureRecognizerShouldBegin中返回false来做到这一点

    class ViewController2: UIViewController, UIGestureRecognizerDelegate {
    ...
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.navigationController?.interactivePopGestureRecognizer.delegate = self
    }
    
    func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
        return false
    }
    

    【讨论】:

    • 请注意 OP 代码中的 UIGestureRecognizer! 与此处的 UIGestureRecognizer
    • 感谢@Hari Kunwar
    【解决方案4】:

    在将视图控制器推送到导航控制器之前添加此行

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
    

    【讨论】:

      【解决方案5】:

      Hari 或 Stefan 的回答都没有错,但这更简洁。只需将其放入 viewDidLoad 即可。

      if navigationController!.respondsToSelector(Selector("interactivePopGestureRecognizer")) {
          navigationController!.view.removeGestureRecognizer(navigationController!.interactivePopGestureRecognizer)
      }
      

      编辑:

      一个小警告是,如果导航控制器被另一个视图打开并且导航控制器关闭,那么您将收到 EXC_BAD_ACCESS 错误。要修复它,您必须保存原始 UIGestureRecognizer 并在退出视图时将其放回原处。

      声明:

      private var popGesture: UIGestureRecognizer?
      

      在移除手势之前:

      popGesture = navigationController!.interactivePopGestureRecognizer
      

      然后在关闭视图时:

      If popGesture != nil {
          navigationController!.view.addGestureRecognizer(popGesture!)
      }
      

      【讨论】:

        【解决方案6】:

        RowanPD 的 Swift 4

        逻辑
        private var popGesture: UIGestureRecognizer?
        
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
        
            if navigationController!.responds(to: #selector(getter: UINavigationController.interactivePopGestureRecognizer)) {
                self.popGesture = navigationController!.interactivePopGestureRecognizer
                self.navigationController!.view.removeGestureRecognizer(navigationController!.interactivePopGestureRecognizer!)
            }
        
        }
        
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
        
            if let gesture = self.popGesture {
                self.navigationController!.view.addGestureRecognizer(gesture)
            }
        
        }
        

        【讨论】:

          【解决方案7】:

          代替

          self.navigationController.pushViewController(VC, animated: Bool)

          打电话

          self.navigationController.setViewContollers([VC], animated: Bool)

          setViewControllers 替换堆栈上的所有 VC,而不是在顶部添加一个新控制器。这意味着新设置的VC是根VC,用户无法返回。

          当您只想在单个 VC 上禁用滑动时,这是最有效的,而为另一个 VC 保留滑动到返回。

          如果您希望用户能够返回,而不是通过滑动,请不要使用此方法,因为它会禁用所有返回(因为没有 VC 可以返回)。

          【讨论】:

          • 太棒了!谢谢!
          【解决方案8】:

          对于目标-c

          -(void)viewWillAppear:(BOOL)animated{
            [super viewWillAppear:true];
          
            self.navigationController.interactivePopGestureRecognizer.enabled = NO;
          
          }
          

          【讨论】:

            【解决方案9】:

            我通常会确保在尽可能多的地方启用向后滑动,甚至添加自定义手势识别器以将其添加到模态屏幕。但是,对于我的应用程序中的身份验证和下载过程,我使用模态导航控制器开始该过程,然后为每个下一步推送视图。但是,一旦完成,我想阻止他们备份到身份验证屏幕。

            对于我一直在使用的这个场景:

            navigationController?.interactivePopGestureRecognizer?.isEnabled = false
            navigationItem.hidesBackButton = true
            

            在最后一屏的viewWillAppear() 中。如果您正在推送另一个视图并在那里需要它们,您可以在 viewWillDisappear() 中撤消这些操作。

            【讨论】:

              【解决方案10】:

              如果您尝试了所有方法后仍然无法正常工作,那么这是您错过的东西。

              1. navigationController?.interactivePopGestureRecognizer?.isEnabled = false 添加到您的 viewWillAppear(animated:) 方法中。
              2. 如果它不起作用,请从视图控制器中删除导航委托。再次检查您的视图控制器是否正在确认UINavigationControllerDelegateUIGestureRecognizerDelegate 协议。如果是这样,只需将其删除。

              【讨论】:

                【解决方案11】:

                如果需要在某些屏幕上显示侧边菜单,则在此特定视图上添加 AddScreenEdgePanGesture 而不是 navigationController 视图

                替换它

                SideMenuManager.default.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController?.view)
                

                有了这个

                SideMenuManager.default.menuAddScreenEdgePanGesturesToPresent(toView: self.view)
                

                【讨论】:

                  【解决方案12】:

                  如果您不关心系统后退按钮的外观(例如,如果您使用自定义后退按钮或导航栏完全隐藏),它可能会对您有所帮助:

                  navigationItem.hidesBackButton = true
                  

                  它隐藏后退按钮并禁用向后滑动手势。

                  【讨论】:

                    【解决方案13】:

                    只有完全删除手势识别器对我有用(来自呈现视图控制器)。

                    if let navigationController = parent.navigationController,
                       let interactivePopGestureRecognizer = navigationController.interactivePopGestureRecognizer {
                        navigationController.view.removeGestureRecognizer(interactivePopGestureRecognizer)
                    }
                    

                    【讨论】:

                      【解决方案14】:

                      如果您不想回来,请不要使用它,或者设置新的 rootViewController。

                      self.navigationController.pushViewController(VC, animated: Bool)
                      

                      使用这个

                      self.navigationController.setViewContollers([VC], animated: Bool)
                      

                      setViewControllers 移除堆栈上的所有视图控制器,然后用户无法返回。它会禁用所有的背部

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2013-06-17
                        • 1970-01-01
                        • 2020-06-17
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多