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

问题描述 投票:315回答:16

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

ios objective-c uinavigationcontroller uigesturerecognizer ios7
16个回答
570
投票

我找到了解决方案:

Objective-C的:

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

斯威夫特3: self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false


3
投票

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

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


3
投票

这是Swift 3的方式

适合我

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

3
投票

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

[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];

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

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


2
投票

这些答案都没有帮助我解决问题。在这里发表我的答案;可能对某人有帮助

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

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
投票

这适用于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 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
    }

}

0
投票

它适用于大多数视图控制器。

self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

它不适用于像UIPageViewController这样的一些视图控制器。在UIPageViewController的pagecontentviewcontroller下面代码为我工作。

override func viewDidLoad() {
   self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
   self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
   self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
   self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
}

在UIGestureRecognizerDelegate上,

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

46
投票

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

修复我的是委托手势并实现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;
}

28
投票

只需从NavigationController中删除手势识别器。在iOS 8中工作。

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

22
投票

从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;
}

20
投票

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

  1. 您的视图控制器可以设置为其他手势识别器的代理
  2. 将代理设置为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;
}

10
投票

请在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;
}

8
投票

对于Swift:

navigationController!.interactivePopGestureRecognizer!.enabled = false

5
投票

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

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

}

它不适用于viewDidLoad()方法。


5
投票

EDIT

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

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

例如:

#import <SwipeBack/SwipeBack.h>

- (void)viewWillAppear:(BOOL)animated
{
    navigationController.swipeBackEnabled = NO;
}

它可以通过CocoaPods安装。

pod 'SwipeBack', '~> 1.0'

我为缺乏解释而道歉。

© www.soinside.com 2019 - 2024. All rights reserved.