it-swarm.com.ru

Как отключить жест смахивания назад в UINavigationController на iOS 7

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

316
ArtFeel

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

Objective-C:

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

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

568
ArtFeel

Я обнаружил, что установка жеста на отключение не всегда работает. Это работает, но для меня это только после того, как я однажды использовал 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;
}
45
Antoine

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

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

Начиная с 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;
}
21
Charlie Seligman

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

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

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

Для Свифта:

navigationController!.interactivePopGestureRecognizer!.enabled = false
8
iPhone 7

Правка

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

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

Например:

#import <SwipeBack/SwipeBack.h>

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

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

pod 'SwipeBack', '~> 1.0'

Я прошу прощения за отсутствие объяснения.

6
devxoul

у меня работает в ios 10 и позже:

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

}

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

5
Logic

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

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

3
SoftDesigner

Это путь к Swift 3

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

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
3
Tayo119

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

[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];

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

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

2
uliwitness

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

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

Обновление

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

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

navigationController?.interactivePopGestureRecognizer?.enabled = false
2
Dannie P

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

Объявите 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 и далее

2
Augustine P A

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

}
1
Mat0

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

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
}
0
Faris Muhammed