Cómo deshabilitar el gesto de deslizar 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 stack de navegación. Pero en mi aplicación, este comportamiento entra en conflicto con mi menú personalizado de la izquierda. Entonces, ¿es posible deshabilitar este nuevo gesto en UINavigationController?

Encontré una solución:

C objective:

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

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

Descubrí que configurar el gesto como desactivado solo no siempre funciona. Funciona, pero para mí solo sucedió después de que una vez usé la contraproducción. La segunda vez no desencadenaría la contracción.

La solución para mí era 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; } 

Simplemente elimine el reconocedor de gestos de NavigationController. Trabaja en iOS 8.

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

A partir de iOS 8, la respuesta aceptada ya no funciona. Necesitaba detener el desplazamiento para descartar el gesto en la pantalla principal de mi 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; } 

He refinado un poco la respuesta de Twan, porque:

  1. su controlador de vista puede establecerse como un delegado a otros reconocedores de gestos
  2. configurar el delegado en nil conduce a problemas de locking cuando vuelve al controlador de vista raíz y hace 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; } 

EDITAR

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

Con esto, puede establecer navigationController.swipeBackEnabled = NO .

Por ejemplo:

 #import  - (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.

me funciona en ios 10 y después:

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

no funciona en el método viewDidLoad ().

Por favor, configure esto en vc raíz:

 -(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:YES]; self.navigationController.interactivePopGestureRecognizer.enabled = NO; } -(void)viewDidDisappear:(BOOL)animated{ [super viewDidDisappear:YES]; self.navigationController.interactivePopGestureRecognizer.enabled = YES; } 

Para Swift:

 navigationController!.interactivePopGestureRecognizer!.enabled = false 

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

Declare private var popGesture: UIGestureRecognizer? como variable global en tu viewcontroller. Luego, implemente 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 desactivará el deslizamiento en iOS v8.x en adelante

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 del buen viejo dispatch_after .

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

Actualizar

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

En iOS 9.3 ya no necesita demoras, funciona simplemente al colocar esto en su viewDidLoad :
(TBD si funciona en iOS 9.0-9.3)

 navigationController?.interactivePopGestureRecognizer?.enabled = false 

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

 [navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer]; 

donde myPanGestureRecognizer es el reconocedor de gestos que está utilizando para, por ejemplo, mostrar su menú. De esta forma, el reconocedor de gestos de Apple no se vuelve a activar cuando presionas un nuevo controlador de navegación y no tienes que depender de demoras desastrosas que pueden activarse demasiado pronto si el teléfono se pone en suspensión o con una carga pesada.

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

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 stack de navigationController!.interactivePopGestureRecognizer!.delegate = nil : navigationController!.interactivePopGestureRecognizer!.delegate = nil

Este es el camino en Swift 3

funciona para mi

  self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false 

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