首页 文章

如何在iOS 7上的UINavigationController中禁用后滑动手势

提问于
浏览
296

在iOS 7中,Apple添加了一个新的默认导航行为 . 您可以从屏幕的左边缘滑动以返回导航堆栈 . 但在我的应用程序中,此行为与我的自定义左菜单冲突 . 那么,是否可以在UINavigationController中禁用这个新手势?

15 回答

  • 17

    对于Swift:

    navigationController!.interactivePopGestureRecognizer!.enabled = false
    
  • 44

    没有给出的答案帮助我解决了这个问题 . 在这里发表我的答案;可能对某人有帮助

    在viewcontroller中将 private var popGesture: UIGestureRecognizer? 声明为全局变量 . 然后在 viewDidAppearviewWillDisappear 方法中实现代码

    override func viewDidAppear(animated: Bool) {
    
        super.viewDidAppear(animated)
    
        if self.navigationController!.respondsToSelector(Selector("interactivePopGestureRecognizer")) {
    
            self.popGesture = navigationController!.interactivePopGestureRecognizer
            self.navigationController!.view.removeGestureRecognizer(navigationController!.interactivePopGestureRecognizer!)
        }
    }
    
    
    override func viewWillDisappear(animated: Bool) {
    
        super.viewWillDisappear(animated)
    
        if self.popGesture != nil {
            navigationController!.view.addGestureRecognizer(self.popGesture!)
        }
    }
    

    这将禁用在iOS v8.x 之后向后滑动

  • 2

    我的方法 . 一个手势识别器来统治它们:

    class DisabledGestureViewController: UIViewController: UIGestureRecognizerDelegate {
        override func viewDidLoad() {
            super.viewDidLoad()
            navigationController!.interactivePopGestureRecognizer!.delegate = self
        }
    
        func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
            // Prevent going back to the previous view
            return !(navigationController!.topViewController is DisabledGestureViewController)
        }
    }
    

    重要提示:不要在导航堆栈中的任何位置重置委托: navigationController!.interactivePopGestureRecognizer!.delegate = nil

  • 7

    我稍微改进了Twan的答案,因为:

    • 您的视图控制器可以设置为其他手势识别器的代理

    • 将委托设置为 nil 导致挂起问题,当您返回到根视图控制器并在导航到其他地方之前进行滑动手势 .

    以下示例假设iOS 7:

    {
        id savedGestureRecognizerDelegate;
    }
    
    - (void)viewWillAppear:(BOOL)animated
    {
        savedGestureRecognizerDelegate = self.navigationController.interactivePopGestureRecognizer.delegate;
        self.navigationController.interactivePopGestureRecognizer.delegate = self;
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
        self.navigationController.interactivePopGestureRecognizer.delegate = savedGestureRecognizerDelegate;
    }
    
    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
    {
        if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
            return NO;
        }
        // add whatever logic you would otherwise have
        return YES;
    }
    
  • 4

    所有这些解决方案都以他们不推荐的方式操纵Apple的手势识别器 . 朋友告诉我,有一个更好的解决方案:

    [navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];
    

    其中myPanGestureRecognizer是您正在使用的手势识别器,例如显示你的菜单 . 这样,当您推动新的导航控制器时,Apple的手势识别器不会被他们拒绝,而您不需要依赖于如果您的手机处于睡眠状态或负载较重时可能会过早发生的诡计 .

    离开这里因为我知道下次我需要它时我不记得了,然后我会在这里解决这个问题 .

  • 26

    从iOS 8开始,接受的答案不再适用 . 我需要停止在我的主游戏屏幕上解除手势,所以实现了这个:

    - (void)viewDidAppear:(BOOL)animated
    {
         [super viewDidAppear:animated];
    
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.delegate = self;
        }
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.delegate = nil;
        }
    
    }
    
    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
    {
         return NO;
    }
    
  • 2

    对于 Swift 4 ,这适用:

    class MyViewController: UIViewController, UIGestureRecognizerDelegate {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.navigationController?.interactivePopGestureRecognizer?.gesture.delegate = self
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(true)
    
            self.navigationController?.interactivePopGestureRecognizer?.gesture.isEnabled = false
        }
    
    }
    
  • 7

    我找到了解决方案:

    Objective-C:

    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    }
    

    Swift 3:
    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

  • 5

    它适用于ios 10及更高版本:

    - (void)viewWillAppear:(BOOL)animated {
        if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
            self.navigationController.interactivePopGestureRecognizer.enabled = NO;
        }
    
    }
    

    它不适用于viewDidLoad()方法 .

  • 21

    编辑

    如果要管理特定导航控制器的滑动功能,请考虑使用SwipeBack .

    有了这个,你可以设置 navigationController.swipeBackEnabled = NO .

    例如:

    #import <SwipeBack/SwipeBack.h>
    
    - (void)viewWillAppear:(BOOL)animated
    {
        navigationController.swipeBackEnabled = NO;
    }
    

    它可以通过CocoaPods安装 .

    pod 'SwipeBack', '~> 1.0'
    

    我为缺乏解释而道歉 .

  • 2

    请在root vc中设置:

    -(void)viewDidAppear:(BOOL)animated{
        [super viewDidAppear:YES];
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    
    }
    
    -(void)viewDidDisappear:(BOOL)animated{
        [super viewDidDisappear:YES];
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
    }
    
  • 2

    我发现将手势设置为禁用只是并不总是有效 . 它确实有效,但对我来说,它只是在我曾经使用过背景后才做到的 . 第二次它不会触发反馈 .

    修复我的是委托手势并实现shouldbegin方法返回NO:

    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
    
        // Disable iOS 7 back gesture
        if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
            self.navigationController.interactivePopGestureRecognizer.enabled = NO;
            self.navigationController.interactivePopGestureRecognizer.delegate = self;
        }
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
    
        // Enable iOS 7 back gesture
        if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
            self.navigationController.interactivePopGestureRecognizer.enabled = YES;
            self.navigationController.interactivePopGestureRecognizer.delegate = nil;
        }
    }
    
    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
    {
        return NO;
    }
    
  • 552

    只需从NavigationController中删除手势识别器 . Work in iOS 8.

    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
        [self.navigationController.view removeGestureRecognizer:self.navigationController.interactivePopGestureRecognizer];
    
  • 2

    适用于iOS 8的 viewDidLoad:

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          self.navigationController.interactivePopGestureRecognizer.enabled = false;
      });
    

    很多问题都可以通过好的' dispatch_after 来解决 .

    虽然请注意此解决方案可能不安全,请使用您自己的推理 .

    更新

    对于iOS 8.1,延迟时间应为0.5秒

    在iOS 9.3上不再需要延迟,只需将其放在 viewDidLoad 中即可:
    (TBD适用于iOS 9.0-9.3)

    navigationController?.interactivePopGestureRecognizer?.enabled = false
    
  • 1

    这是Swift 3的方式

    适合我

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
    

相关问题