Cómo deshabilitar el gesto de deslizamiento hacia atrás en UINavigationController en iOS 7


En iOS 7 Apple agregó un nuevo comportamiento de navegación predeterminado. Puede deslizar desde el borde izquierdo de la pantalla para volver a la pila de navegación. Pero en mi aplicación, este comportamiento entra en conflicto con mi menú izquierdo personalizado. Entonces, ¿es posible desactivar este nuevo gesto en UINavigationController?

Author: hfossli, 2013-06-20

15 answers

Encontré una solución:

Objetivo-C:

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

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

 541
Author: ArtFeel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-15 09:25:11

Descubrí que establecer el gesto en solo deshabilitado no siempre funciona. Funciona, pero para mí solo lo hizo después de que una vez usé el backgesture. La segunda vez no activaría la backgesture.

La solución para mí fue delegar el gesto e implementar el método shouldbegin para devolver 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;
}
 44
Author: Antoine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-24 14:28:32

Simplemente elimine gesture recognizer de NavigationController. Funciona en iOS 8.

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
    [self.navigationController.view removeGestureRecognizer:self.navigationController.interactivePopGestureRecognizer];
 26
Author: Vladimir Samoylov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-21 10:01:57

A partir de iOS 8, la respuesta aceptada ya no funciona. Necesitaba detener el movimiento para despedir el gesto en mi pantalla principal del juego, así que implementé esto:

- (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
Author: Charlie Seligman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-01 17:50:52

He refinado un poco la respuesta de Twan, porque:

  1. su controlador de vista puede configurarse como delegado para otros reconocedores de gestos
  2. establecer el delegado en nil conduce a problemas de suspensión cuando regresa al controlador de vista raíz y realiza un gesto de deslizamiento antes de navegar en otro lugar.

El siguiente ejemplo asume 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;
}
 17
Author: Ja͢ck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-17 04:12:11

EDITAR

Si desea administrar la función deslizar hacia atrás para controladores de navegación específicos, considere usar Deslizar hacia atrás.

Con esto, puede establecer navigationController.swipeBackEnabled = NO.

Por ejemplo:

#import <SwipeBack/SwipeBack.h>

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

Se puede instalar a través de CocoaPods.

pod 'SwipeBack', '~> 1.0'

Me disculpo por la falta de explicación.

 7
Author: devxoul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-06 04:42:20

Por favor, establezca esto en la raíz 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;
}
 6
Author: reza_khalafi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-04 05:43:34

Funciona para mí en ios 10 y posteriores:

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

}

No funciona con el método viewDidLoad ().

 5
Author: Logic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-03 10:23:27

Para Swift:

navigationController!.interactivePopGestureRecognizer!.enabled = false
 4
Author: iPhone 7,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-06 04:41:53

Ninguna de las respuestas dadas me ayudó a resolver el problema. Publicar mi respuesta aquí; puede ser útil para alguien

Declare private var popGesture: UIGestureRecognizer? como variable global en su viewcontroller. Luego implementa el código en los métodos viewDidAppear y 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!)
    }
}

Esto deshabilitará el deslizamiento hacia atrás en iOS v8.x en adelante

 2
Author: Augustine P A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-05 11:54:46

Esto funciona en viewDidLoad: para 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;
  });

Muchos de los problemas podrían resolverse con la ayuda de los buenos dispatch_after.

Aunque tenga en cuenta que esta solución es potencialmente insegura, utilice su propio razonamiento.

Update

Para iOS 8.1 el tiempo de retardo debe ser de 0.5 segundos

En iOS 9.3 no se necesita más demora, funciona simplemente colocando esto en su viewDidLoad:
(Por determinar si funciona en iOS 9.0-9.3)

navigationController?.interactivePopGestureRecognizer?.enabled = false
 2
Author: Dannie P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-12 12:56:26

Todas estas soluciones manipulan el reconocedor de gestos de Apple de una manera que no recomiendan. Un amigo me acaba de decir que hay una solución mejor:

[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];

Donde myPanGestureRecognizer es el reconocedor de gestos que está utilizando para, por ejemplo, mostrar su menú. De esa manera, el reconocedor de gestos de Apple no se vuelve a activar cuando presionas un nuevo controlador de navegación y no necesitas depender de retrasos skanky que pueden dispararse demasiado temprano si tu teléfono se pone en reposo o bajo carga pesada.

Dejando esto aquí porque sé que no lo recordaré la próxima vez que lo necesite, y luego tendré la solución al problema aquí.

 2
Author: uliwitness,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-26 14:16:30

Mi método. Un reconocedor de gestos para gobernarlos a todos:

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

Importante: no restablezca el delegado en ninguna parte de la pila de navegación: navigationController!.interactivePopGestureRecognizer!.delegate = nil

 2
Author: SoftDesigner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-28 08:55:08

Este es el camino en Swift 3

Funciona para mí

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
 2
Author: Tayo119,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-13 11:50:04

Para Swift 4 esto funciona:

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
    }

}
 1
Author: Mat0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-20 15:01:41