简体   繁体   English

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

[英]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 的回答,因为:

  1. your view controller may be set as a delegate to other gesture recognisers您的视图控制器可能被设置为其他手势识别器的委托
  2. setting the delegate to 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

EDIT编辑

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.尽管请注意此解决方案可能不安全,但请使用您自己的推理。

Update更新

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然后在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!)
    }
}

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.

相关问题 如何在iOS 8中的UINavigationController中禁用后退滑动手势? - How do disable back swipe gesture in UINavigationController in iOS 8? 如何在iOS 7的UINavigationController中创建自定义向后滑动手势 - How to create custom back swipe gesture in UINavigationController on iOS 7 在 UINavigationController 中覆盖向后滑动手势 - Overriding back swipe gesture in UINavigationController 将UIPageViewController滑动与iOS 7 UINavigationController反滑动手势相结合 - Combine UIPageViewController swipes with iOS 7 UINavigationController back-swipe gesture 如何禁用向后/向左滑动手势? - How to disable back/left swipe gesture? 设置 leftBarButtonItem 后如何在 UINavigationController 中启用向后/向左滑动手势? - How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem? 有没有办法在反应原生 iOS 时有条件地禁用对 go 后退手势的滑动? - Is there a way to conditionally disable the swipe to go back gesture in react native iOS? 在 Swift 中禁用向后滑动手势 - Disable swipe back gesture in Swift 如何在 ios 11 中使用主从视图禁用向后滑动手势? - How to disable swipe back gesture with master-detail view in ios 11? 如何在反应原生导航器中禁用反向滑动手势 - How to disable back swipe gesture in react native navigator
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM