Как отключить жест обратного свайпа в UINavigationController на iOS 7



в iOS 7 Apple добавила новое поведение навигации по умолчанию. Вы можете провести пальцем от левого края экрана, чтобы вернуться в стек навигации. Но в моем приложении это поведение конфликтует с моим пользовательским левым меню. Итак, можно ли отключить этот новый жест в UINavigationController?

759   15  

15 ответов:

Я нашел решение:

Цель-C:

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

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

я узнал, что установка жеста только для инвалидов не всегда работает. Это действительно работает, но для меня это произошло только после того, как я однажды использовал backgesture. Во второй раз это не вызовет backgesture.

исправить для меня было делегировать жест и реализовать метод 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 принятый ответ больше не работает. Мне нужно было остановить swipping, чтобы отклонить жест на моем главном игровом экране, чтобы реализовать это:

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

Я немного уточнил ответ Твана, потому что:

  1. ваш контроллер может быть установлен в качестве делегата на другие жест recognisers
  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;
}

EDIT

если вы хотите управлять функцией swipe back для конкретных навигационных контроллеров, рассмотрите возможность использования SwipeBack.

С этим, вы можете установить navigationController.swipeBackEnabled = NO.

например:

#import <SwipeBack/SwipeBack.h>

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

его можно установить через CocoaPods.

pod 'SwipeBack', '~> 1.0'

Я извиняюсь за отсутствие объяснений.

пожалуйста, установите это в корневой 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;
}

он работает для меня в ios 10 и более поздних версиях:

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

}

он не работает на метод viewDidLoad() метод.

Для Swift:

navigationController!.interactivePopGestureRecognizer!.enabled = false

ни один из приведенных ответов не помог мне решить эту проблему. Размещение мой ответ здесь; может быть полезно для кого-то

объявить private var popGesture: UIGestureRecognizer? как глобальная переменная в вашем viewcontroller. Затем реализовать код в 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 далее

это работает в 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;
  });

многие проблемы могут быть решены с помощью хорошего ol'dispatch_after.

хотя обратите внимание, что это решение потенциально небезопасно, пожалуйста, используйте свои собственные рассуждения.

обновление

для iOS 8.1 Время задержки должно быть 0,5 секунды

на iOS 9.3 больше не требуется задержка, она работает, просто поместив это в свой viewDidLoad:
(TBD если работает на iOS 9.0-9.3)

navigationController?.interactivePopGestureRecognizer?.enabled = false

все эти решения управляют распознавателем жестов Apple таким образом, который они не рекомендуют. Мне только что сказал друг, что есть лучшее решение:

[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];

где myPanGestureRecognizer-это распознаватель жестов, который вы используете, например, для отображения меню. Таким образом, распознаватель жестов Apple не включается ими, когда вы нажимаете новый навигационный контроллер, и вам не нужно полагаться на жуткие задержки, которые могут сработать слишком рано, если ваш телефон переведен в режим сна или под тяжелым грузом.

оставляя это здесь, потому что я знаю, что не буду помнить об этом в следующий раз, когда мне это понадобится, и тогда у меня будет решение проблемы здесь.

мой метод. Один распознаватель жестов, чтобы управлять ими всеми:

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

Это путь на Swift 3

для меня

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

на 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 = true
    }

}

Comments

    Ничего не найдено.