[英]How to disable back swipe gesture in UINavigationController on iOS 7
In iOS 7 Apple added a new default navigation behavior.在 iOS 7 Apple 添加了新的默认导航行为。 You can swipe from the left edge of the screen to go back on the navigation stack.
您可以从屏幕的左边缘滑动到导航堆栈上的 go。 But in my app, this behavior conflicts with my custom left menu.
但在我的应用程序中,此行为与我的自定义左侧菜单冲突。 So, is it possible to disable this new gesture in UINavigationController?
那么,是否可以在 UINavigationController 中禁用此新手势?
I found a solution:我找到了一个解决方案:
Objective-C:目标-C:
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
Swift 3+:斯威夫特 3+:
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
I found out setting the gesture to disabled only doesn't always work.我发现将手势设置为仅禁用并不总是有效。 It does work, but for me it only did after I once used the backgesture.
它确实有效,但对我来说只有在我使用过 backgesture 之后才有效。 Second time it wouldn't trigger the backgesture.
第二次它不会触发backgesture。
Fix for me was to delegate the gesture and implement the shouldbegin method to return NO:对我来说修复是委托手势并实现 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;
}
Just remove gesture recognizer from NavigationController.只需从 NavigationController 中删除手势识别器。 Work in iOS 8.
在 iOS 8 中工作。
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
[self.navigationController.view removeGestureRecognizer:self.navigationController.interactivePopGestureRecognizer];
As of iOS 8 the accepted answer no longer works.从 iOS 8 开始,接受的答案不再有效。 I needed to stop the swipping to dismiss gesture on my main game screen so implemented this:
我需要停止在我的主游戏屏幕上滑动以关闭手势,所以实现了这个:
- (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;
}
I've refined Twan's answer a bit, because:我稍微改进了 Twan 的回答,因为:
nil
leads to hanging issues when you go back to the root view controller and make a swipe gesture before navigating elsewhere.nil
会导致挂起问题。 The following example assumes iOS 7:以下示例假设为 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;
}
对于斯威夫特:
navigationController!.interactivePopGestureRecognizer!.enabled = false
Please set this in root vc:请在根 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;
}
swift 5, swift 4.2 can use the code in the below. swift 5、swift 4.2 可以使用下面的代码。
// disable
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
// enable
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
If you want to manage swipe back feature for specific navigation controllers, consider using SwipeBack .如果您想管理特定导航控制器的向后滑动功能,请考虑使用SwipeBack 。
With this, you can set navigationController.swipeBackEnabled = NO
.有了这个,你可以设置
navigationController.swipeBackEnabled = NO
。
For example:例如:
#import <SwipeBack/SwipeBack.h>
- (void)viewWillAppear:(BOOL)animated
{
navigationController.swipeBackEnabled = NO;
}
It can be installed via CocoaPods .它可以通过CocoaPods安装。
pod 'SwipeBack', '~> 1.0'
I appologize for lack of explanation.我为缺乏解释而道歉。
it works for me in ios 10 and later :它适用于 ios 10 及更高版本:
- (void)viewWillAppear:(BOOL)animated {
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
}
it doesnt work on viewDidLoad() method.它不适用于 viewDidLoad() 方法。
My method.我的方法。 One gesture recognizer to rule them all:
一个手势识别器来统治他们:
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)
}
}
Important: don't reset the delegate anywhere in the navigation stack: navigationController!.interactivePopGestureRecognizer!.delegate = nil
重要提示:不要在导航堆栈中的任何位置重置委托:
navigationController!.interactivePopGestureRecognizer!.delegate = nil
This is the way on Swift 3这是 Swift 3 的方式
works for me为我工作
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
All of these solutions manipulate Apple's gesture recognizer in a way they do not recommend.所有这些解决方案都以他们不推荐的方式操纵 Apple 的手势识别器。 I've just been told by a friend that there's a better solution:
一位朋友刚刚告诉我,有一个更好的解决方案:
[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];
where myPanGestureRecognizer is the gesture recognizer you are using to eg show your menu.其中 myPanGestureRecognizer 是您用来显示菜单的手势识别器。 That way, Apple's gesture recognizer doesn't get turned back on by them when you push a new navigation controller and you don't need to rely on hacky delays that may fire too early if your phone is put to sleep or under heavy load.
这样,当您按下新的导航控制器时,Apple 的手势识别器不会被它们重新打开,并且您不需要依赖可能会在您的手机进入睡眠状态或负载过重时过早触发的黑客延迟。
Leaving this here because I know I'll not remember this the next time I need it, and then I'll have the solution to the issue here.把它留在这里是因为我知道下次需要它时我不会记住它,然后我会在这里找到问题的解决方案。
This works in viewDidLoad:
for iOS 8:这适用于
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;
});
Lots of the problems could be solved with help of the good ol' dispatch_after
.很多问题都可以在好的 ol'
dispatch_after
帮助下解决。
Though please note that this solution is potentially unsafe, please use your own reasoning.尽管请注意此解决方案可能不安全,但请使用您自己的推理。
For iOS 8.1 delay time should be 0.5 seconds对于 iOS 8.1 延迟时间应该是 0.5 秒
On iOS 9.3 no delay needed anymore, it works just by placing this in your viewDidLoad
:在 iOS 9.3 上不再需要延迟,只需将它放在您的
viewDidLoad
:
(TBD if works on iOS 9.0-9.3) (待定,如果适用于 iOS 9.0-9.3)
navigationController?.interactivePopGestureRecognizer?.enabled = false
None of the given answers helped me to resolve the issue.给出的答案都没有帮助我解决问题。 Posting my answer here;
在这里发布我的答案; may be helpful for someone
可能对某人有帮助
Declare private var popGesture: UIGestureRecognizer?
声明
private var popGesture: UIGestureRecognizer?
as global variable in your viewcontroller.作为视图控制器中的全局变量。 Then implement the code in viewDidAppear and viewWillDisappear methods
然后在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!)
}
}
This will disable swipe back in iOS v8.x onwards这将在 iOS v8.x之后禁用向后滑动
For Swift 4 this works:对于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
}
}
It worked for me for most of the viewcontrollers.它适用于大多数视图控制器。
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
It wasn't not working for some viewcontrollers like UIPageViewController.它不适用于某些视图控制器,例如 UIPageViewController。 On UIPageViewController's pagecontentviewcontroller below code worked for me.
在 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
}
On UIGestureRecognizerDelegate,在 UIGestureRecognizerDelegate 上,
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer {
return false
}
return true
}
self.navigationController.pushViewController(VC, animated: Bool)
call称呼
self.navigationController.setViewContollers([VC], animated: Bool)
setViewControllers replaces all the VCs on the stack, instead of adding a new controller on top. setViewControllers 替换堆栈中的所有 VC,而不是在顶部添加新的 controller。 This means that the new set VC is the root VC, and the user cannot go back.
这意味着新设置的VC是根VC,用户不能go回来。
This is most effective when you only want to disable the swipe on a single VC and keep the swipe-to-back for the other VC.当您只想禁用单个 VC 上的滑动并为另一个 VC 保持向后滑动时,这是最有效的。
If you want users to be able to go back, just not through swiping, do not use this method as it will disable all backs (as there is no VC to go back to)如果您希望用户能够返回 go,而不是通过滑动,请不要使用此方法,因为它会禁用所有返回(因为没有 VC 到 go 返回)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.