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

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

Ответ 1

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

Objective-C:

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

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

Ответ 2

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

Исправить для меня было делегировать жест и реализовать метод 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;
}

Ответ 3

Просто удалите распознаватель жестов из NavigationController. Работа в iOS 8.

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

Ответ 4

Как и в 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;
}

Ответ 5

Я немного уточнил Twan, потому что:

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

Ответ 6

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

Ответ 7

Для Swift:

navigationController!.interactivePopGestureRecognizer!.enabled = false

Ответ 8

ИЗМЕНИТЬ

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

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

Например:

#import <SwipeBack/SwipeBack.h>

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

Он может быть установлен через CocoaPods.

pod 'SwipeBack', '~> 1.0'

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

Ответ 9

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

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

}

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

Ответ 10

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

[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];

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

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

Ответ 11

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

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)
    }
}

Важно: не reset делегат в любом месте стека навигации: navigationController!.interactivePopGestureRecognizer!.delegate = nil

Ответ 12

Это путь на Swift 3

работает для меня

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

Ответ 13

Это работает в 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

Ответ 14

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

Объявить 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 вперед

Ответ 15

Для 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
    }

}

Ответ 16

У меня это работало для большинства контроллеров представления.

self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

Это не работает для некоторых контроллеров представления, таких как UIPageViewController. На странице управления контентом UIPageViewController ниже код работал для меня.

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
}