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

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

我find一个解决scheme:

Objective-C的:

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

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

我发现将手势设置为禁用,并不总是工作。 它确实有用,但是对我来说,它只是在我曾经使用过背后的事情之后才做的。 第二次,它不会引起背痛。

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

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

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

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

我已经细化了Twan的答案,因为:

  1. 您的视图控制器可能被设置为其他手势识别器的委托
  2. nil设置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; } 

编辑

如果要pipe理特定导航控制器的向后滑动function,请考虑使用“ SwipeBack” 。

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

例如:

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

它可以通过CocoaPods安装。

 pod 'SwipeBack', '~> 1.0' 

我为没有解释而道歉。

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

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

它不适用于viewDidLoad()方法。

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

声明private var popGesture: UIGestureRecognizer? 作为您的视图控制器中的全局variables。 然后在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以后的

这在viewDidLoad:对于iOS 8:

  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

虽然请注意,这个解决scheme可能是不安全的,请使用你自己的推理。

更新

对于iOS 8.1延迟时间应该是0.5秒

在iOS 9.3中不再需要延迟,只需将它放在viewDidLoad
(待定如果在iOS 9.0-9.3上运行)

 navigationController?.interactivePopGestureRecognizer?.enabled = false 

对于Swift:

 self.navigationController!.interactivePopGestureRecognizer!.enabled = false 

这是Swift 3上的方式

为我工作

  self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false 

所有这些解决scheme都以他们不推荐的方式操纵苹果的手势识别器。 我刚刚被朋友告知,有一个更好的解决scheme:

 [navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer]; 

myPanGestureRecognizer是您用来显示菜单的手势识别器。 这样,当你推动一个新的导航控制器时,苹果公司的手势识别器不会被他们重新启用,而且你不需要依赖如果你的手机进入睡眠或负载较重的情况下可能会过早发生的时髦延迟。

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

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

 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

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