No deslizar hacia atrás al ocultar la barra de navegación en UINavigationController

86

Me encanta el paquete de deslizamiento que se hereda de incrustar sus vistas en un archivo UINavigationController. Desafortunadamente, parece que no puedo encontrar una manera de ocultar el NavigationBardeslizamiento de la bandeja táctil, pero aún así gesture. Puedo escribir gestos personalizados, pero prefiero no hacerlo y confiar en el UINavigationControllerdeslizamiento hacia atrás gesture.

si lo desmarco en el guión gráfico, el deslizamiento hacia atrás no funciona

ingrese la descripción de la imagen aquí

alternativamente, si lo oculto programáticamente, el mismo escenario.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.navigationController setNavigationBarHidden:YES animated:NO]; // and animated:YES
}

¿No hay forma de ocultar la parte superior NavigationBary seguir teniendo el deslizamiento?

mihai
fuente
1
¿Es aceptable agregar un UIGestureRecognizer? Es muy fácil de implementar.
SwiftArchitect
1
@LancelotdelaMare, estaba tratando de evitar eso ya que no funcionará tan bien como el deslizamiento hacia atrás de UINavigationController. Estoy buscando en UIScreenEdgePanGestureRecognizer ya que algunas personas dicen que ayuda, pero aún no lo han hecho funcionar. Buscando aquí la solución más sencilla y elegante.
mihai

Respuestas:

96

Un truco que está trabajando es establecer la interactivePopGestureRecognizer's delegado de la UINavigationControllerde nilla siguiente manera:

[self.navigationController.interactivePopGestureRecognizer setDelegate:nil];

Pero en algunas situaciones podría crear efectos extraños.

HorseT
fuente
16
"Deslizar el dedo hacia atrás repetidamente puede hacer que el gesto sea reconocido cuando solo hay un controlador de vista en la pila, lo que a su vez coloca una interfaz de usuario en un estado (creo que inesperado para los ingenieros de UIKit) donde deja de reconocer cualquier gesto"
HorseT
4
Una alternativa que podría proteger contra ese estado inesperada sería establecer a algún objeto bajo nivel (he usado mi delegado de la aplicación) y poner en práctica gestureRecognizerShouldBegin, volviendo truesi el navigationController's viewControllerrecuento es mayor que 0.
Kenny Winker
4
Aunque esto funciona, recomiendo encarecidamente no hacerlo. Romper el delegado estaba provocando un bloque de hilo principal raro y difícil de identificar. Resulta que no es un bloque de hilo principal, pero es lo que describió @HorseT.
Josh Bernfeld
3
Mi aplicación guarda el identificador del delegado, luego lo restaura viewWillDisappeary hasta ahora no ha experimentado efectos secundarios adversos.
Don Park
1
!!!! Se desaconseja usar esta solución, cuando se usa repetidamente el deslizamiento, se produce un comportamiento extraño, la parte posterior está deshabilitada y la aplicación completa ya no responde
KarimIhab
79

Problemas con otros métodos

Establecer el interactivePopGestureRecognizer.delegate = niltiene efectos secundarios no deseados.

La configuración navigationController?.navigationBar.hidden = truefunciona, pero no permite ocultar los cambios en la barra de navegación.

Por último, generalmente es una mejor práctica crear un objeto de modelo que sea UIGestureRecognizerDelegatepara su controlador de navegación. Establecerlo en un controlador en la UINavigationControllerpila es lo que está causando los EXC_BAD_ACCESSerrores.

Solución completa

Primero, agregue esta clase a su proyecto:

class InteractivePopRecognizer: NSObject, UIGestureRecognizerDelegate {

    var navigationController: UINavigationController

    init(controller: UINavigationController) {
        self.navigationController = controller
    }

    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return navigationController.viewControllers.count > 1
    }

    // This is necessary because without it, subviews of your top controller can
    // cancel out your gesture recognizer on the edge.
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

Luego, configure su controlador de navegación interactivePopGestureRecognizer.delegateen una instancia de su nueva InteractivePopRecognizerclase.

var popRecognizer: InteractivePopRecognizer?

override func viewDidLoad() {
    super.viewDidLoad()
    setInteractiveRecognizer()
}

private func setInteractiveRecognizer() {
    guard let controller = navigationController else { return }
    popRecognizer = InteractivePopRecognizer(controller: controller)
    controller.interactivePopGestureRecognizer?.delegate = popRecognizer
}

Disfrute de una barra de navegación oculta sin efectos secundarios, que funciona incluso si su controlador superior tiene subvistas de vista de tabla, colección o desplazamiento.

Monje cazador
fuente
1
¡Gran solución!
Matt Butler
1
La mejor respuesta, ¡Gracias!
Dory Daniel
2
@HunterMaximillionMonk gracias por la gran solución. Funciona a las
mil maravillas
1
@HunterMaximillionMonk, esto parece funcionar correctamente, pero el problema cuando tengo varios controladores, luego de una vez, deja de funcionar.
Premal Khetani
1
¡Definitivamente la mejor respuesta!
2017
54

En mi caso, para evitar efectos extraños

Controlador de vista raíz

override func viewDidLoad() {
    super.viewDidLoad()

    // Enable swipe back when no navigation bar
    navigationController?.interactivePopGestureRecognizer?.delegate = self 

}


func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    if(navigationController!.viewControllers.count > 1){
        return true
    }
    return false
}

http://www.gampood.com/pop-viewcontroller-with-out-navigation-bar/

saranpol
fuente
2
A veces obtengo EXC_BAD_ACCESS cuando uso esto
Andrey Gordeev
Para mí, no hace que el gesto funcione y con frecuencia se bloquea con elEXEC_BAD_ACCESS
Benjohn
2
Recuerde agregar UIGestureRecognizerDelegateal controlador de vista raíz ... En mi caso, el delegado se configuró en nulo en un controlador de vista posterior al controlador de vista raíz, por lo que cuando se devolvió al controlador de vista raíz, gestureRecognizerShouldBeginno se llamó. Así que coloqué el .delegate = selfin viewDidAppear(). Eso solucionó los extraños efectos en mi caso .. ¡Salud!
Wiingaard
@AndreyGordeev ¿Podría darnos algunos detalles sobre cuándo EXEC_BAD_ACCESSsucede?
Jaybo
Aquí hay más información sobre el EXC_BAD_ACCESSerror: stackoverflow.com/questions/28746123/…
Andrey Gordeev
25

Actualizado para iOS 13.4

iOS 13.4 rompió la solución anterior, por lo que las cosas se pondrán feas. Parece que en iOS 13.4 este comportamiento ahora está controlado por un método privado _gestureRecognizer:shouldReceiveEvent:(no debe confundirse con el nuevo shouldReceivemétodo público agregado en iOS 13.4).


Descubrí que otras soluciones publicadas que anulaban al delegado o lo configuraban como nulo causaron un comportamiento inesperado.

En mi caso, cuando estaba en la parte superior de la pila de navegación e intenté usar el gesto para hacer estallar uno más, fallaría (como se esperaba), pero los intentos posteriores de empujar hacia la pila comenzarían a causar fallas gráficas extrañas en el barra de navegación. Esto tiene sentido, porque el delegado se está utilizando para manejar más que solo si se debe bloquear o no el gesto para que no se reconozca cuando la barra de navegación está oculta y todo ese otro comportamiento se descarta.

Según mis pruebas, parece que gestureRecognizer(_:, shouldReceiveTouch:)es el método que está implementando el delegado original para evitar que el gesto sea reconocido cuando la barra de navegación está oculta, no gestureRecognizerShouldBegin(_:). Otras soluciones que implementan gestureRecognizerShouldBegin(_:)en su trabajo delegado debido a la falta de una implementación degestureRecognizer(_:, shouldReceiveTouch:) provocará el comportamiento predeterminado de recibir todos los toques.

La solución de @Nathan Perry se acerca, pero sin una implementación de respondsToSelector(_:), el código UIKit que envía mensajes al delegado creerá que no hay implementación para ninguno de los otros métodos de delegado, yforwardingTargetForSelector(_:) nunca será llamado.

Por lo tanto, tomamos el control de `GestureRecognizer (_ :, shouldReceiveTouch :) en el escenario específico en el que queremos modificar el comportamiento y, de lo contrario, reenviar todo lo demás al delegado.

class AlwaysPoppableNavigationController : UINavigationController {

    private var alwaysPoppableDelegate: AlwaysPoppableDelegate!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.alwaysPoppableDelegate = AlwaysPoppableDelegate(navigationController: self, originalDelegate: self.interactivePopGestureRecognizer!.delegate!)
        self.interactivePopGestureRecognizer!.delegate = self.alwaysPoppableDelegate
    }
}

private class AlwaysPoppableDelegate : NSObject, UIGestureRecognizerDelegate {

    weak var navigationController: AlwaysPoppableNavigationController?
    weak var originalDelegate: UIGestureRecognizerDelegate?

    init(navigationController: AlwaysPoppableNavigationController, originalDelegate: UIGestureRecognizerDelegate) {
        self.navigationController = navigationController
        self.originalDelegate = originalDelegate
    }

    // For handling iOS before 13.4
    @objc func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if let navigationController = navigationController, navigationController.isNavigationBarHidden && navigationController.viewControllers.count > 1 {
            return true
        }
        else if let originalDelegate = originalDelegate {
            return originalDelegate.gestureRecognizer!(gestureRecognizer, shouldReceive: touch)
        }
        else {
            return false
        }
    }

    // For handling iOS 13.4+
    @objc func _gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceiveEvent event: UIEvent) -> Bool {
        if let navigationController = navigationController, navigationController.isNavigationBarHidden && navigationController.viewControllers.count > 1 {
            return true
        }
        else if let originalDelegate = originalDelegate {
            let selector = #selector(_gestureRecognizer(_:shouldReceiveEvent:))
            if originalDelegate.responds(to: selector) {
                let result = originalDelegate.perform(selector, with: gestureRecognizer, with: event)
                return result != nil
            }
        }

        return false
    }

    override func responds(to aSelector: Selector) -> Bool {
        if #available(iOS 13.4, *) {
            // iOS 13.4+ does not need to override responds(to:) behavior, it only uses forwardingTarget
            return originalDelegate?.responds(to: aSelector) ?? false
        }
        else {
            if aSelector == #selector(gestureRecognizer(_:shouldReceive:)) {
                return true
            }
            else {
                return originalDelegate?.responds(to: aSelector) ?? false
            }
        }
    }

    override func forwardingTarget(for aSelector: Selector) -> Any? {
        if #available(iOS 13.4, *), aSelector == #selector(_gestureRecognizer(_:shouldReceiveEvent:)) {
            return nil
        }
        else {
            return self.originalDelegate
        }
    }
}
Chris Vasselli
fuente
1
Parece que tu solución es la mejor para este momento. ¡Gracias!
Timur Bernikovich
"pero los intentos posteriores de empujar a la pila comenzarían a causar extraños fallos gráficos en la barra de navegación" - Estoy confundido aquí. Pensé que no teníamos barra de navegación. ¿Esa es la pregunta? En mi situación, tengo un controlador de navegación integrado como controlador de vista infantil sin barra de navegación; el VC que lo contiene tiene los controles de navegación. Así que dejé que el VC que lo contiene sea el delegado del reconocedor y simplemente hice la gestureRecognizerShouldBegin:cosa, y "parece funcionar". Me pregunto si debería estar atento.
skagedal
2
Esto tuvo una pérdida de memoria ya que navigationControllerera una fuerte referencia en AlwaysPoppableDelegate. He editado el código para que sea una weakreferencia.
Graham Perks
3
Esta buena solución ya no funciona en iOS 13.4
Ely
@ChrisVasselli Realmente increíble, ¡gracias! Con suerte, esto pasará la verificación de métodos privados de la revisión de la App Store.
Ely
16

Puede subclase UINavigationController de la siguiente manera:

@interface CustomNavigationController : UINavigationController<UIGestureRecognizerDelegate>

@end

Implementación:

@implementation CustomNavigationController

- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {
    [super setNavigationBarHidden:hidden animated:animated];
    self.interactivePopGestureRecognizer.delegate = self;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if (self.viewControllers.count > 1) {
        return YES;
    }
    return NO;
}

@end
Yogesh Maheshwari
fuente
2
El uso de este enfoque es romper el gesto pop en el UIPageViewControllerdesplazamiento.
Atulkhatri
Encontré que viewController.count> 1 verificación es necesaria. Si el usuario intenta deslizar hacia atrás solo con el VC raíz, la interfaz de usuario se bloqueará en la próxima inserción de VC.
VaporwareWolf
11

Respuesta simple, sin efectos secundarios

Si bien la mayoría de las respuestas aquí son buenas, aparentemente tienen efectos secundarios no deseados (ruptura de la aplicación) o son detalladas.

La solución más simple pero funcional que pude encontrar fue la siguiente:

En el ViewController que está ocultando la barra de navegación,

class MyNoNavBarViewController: UIViewController {
    
    // needed for reference when leaving this view controller
    var initialInteractivePopGestureRecognizerDelegate: UIGestureRecognizerDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // we will need a reference to the initial delegate so that when we push or pop.. 
        // ..this view controller we can appropriately assign back the original delegate
        initialInteractivePopGestureRecognizerDelegate = self.navigationController?.interactivePopGestureRecognizer?.delegate
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        // we must set the delegate to nil whether we are popping or pushing to..
        // ..this view controller, thus we set it in viewWillAppear()
        self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(true)

        // and every time we leave this view controller we must set the delegate back..
        // ..to what it was originally
        self.navigationController?.interactivePopGestureRecognizer?.delegate = initialInteractivePopGestureRecognizerDelegate
    }
}

Otras respuestas han sugerido simplemente establecer el delegado en cero. Al deslizar el dedo hacia atrás hasta el controlador de vista inicial en la pila de navegación, se desactivan todos los gestos. Algún tipo de supervisión, quizás, de los desarrolladores de UIKit / UIGesture.

Además, algunas respuestas aquí que he implementado dieron como resultado un comportamiento de navegación de Apple no estándar (específicamente, lo que permite la capacidad de desplazarse hacia arriba o hacia abajo mientras también desliza hacia atrás). Estas respuestas también parecen un poco detalladas y, en algunos casos, incompletas.

CodyB
fuente
viewDidLoad()no es un buen lugar para capturar, initialInteractivePopGestureRecognizerDelegateya que navigationControllerpodría ser nulo allí (aún no se ha colocado en la pila). viewWillAppeardel lugar donde se esconde la barra de navegación sería más apropiado
nCod3d
10

Partiendo de la respuesta de Hunter Maximillion Monk , creé una subclase para UINavigationController y luego configuré la clase personalizada para mi UINavigationController en mi guión gráfico. El código final para las dos clases se ve así:

InteractivePopRecognizer:

class InteractivePopRecognizer: NSObject {

    // MARK: - Properties

    fileprivate weak var navigationController: UINavigationController?

    // MARK: - Init

    init(controller: UINavigationController) {
        self.navigationController = controller

        super.init()

        self.navigationController?.interactivePopGestureRecognizer?.delegate = self
    }
}

extension InteractivePopRecognizer: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return (navigationController?.viewControllers.count ?? 0) > 1
    }

    // This is necessary because without it, subviews of your top controller can cancel out your gesture recognizer on the edge.
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

HiddenNavBarNavigationController:

class HiddenNavBarNavigationController: UINavigationController {

    // MARK: - Properties

    private var popRecognizer: InteractivePopRecognizer?

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        setupPopRecognizer()
    }

    // MARK: - Setup

    private func setupPopRecognizer() {
        popRecognizer = InteractivePopRecognizer(controller: self)
    }
}

Guión gráfico:

Clase personalizada del controlador de navegación del guión gráfico

Tylermilner
fuente
8

Parece que la solución proporcionada por @ChrisVasseli es la mejor. Me gustaría proporcionar la misma solución en Objective-C porque la pregunta es sobre Objective-C (ver etiquetas)

@interface InteractivePopGestureDelegate : NSObject <UIGestureRecognizerDelegate>

@property (nonatomic, weak) UINavigationController *navigationController;
@property (nonatomic, weak) id<UIGestureRecognizerDelegate> originalDelegate;

@end

@implementation InteractivePopGestureDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (self.navigationController.navigationBarHidden && self.navigationController.viewControllers.count > 1) {
        return YES;
    } else {
        return [self.originalDelegate gestureRecognizer:gestureRecognizer shouldReceiveTouch:touch];
    }
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    if (aSelector == @selector(gestureRecognizer:shouldReceiveTouch:)) {
        return YES;
    } else {
        return [self.originalDelegate respondsToSelector:aSelector];
    }
}

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return self.originalDelegate;
}

@end

@interface NavigationController ()

@property (nonatomic) InteractivePopGestureDelegate *interactivePopGestureDelegate;

@end

@implementation NavigationController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.interactivePopGestureDelegate = [InteractivePopGestureDelegate new];
    self.interactivePopGestureDelegate.navigationController = self;
    self.interactivePopGestureDelegate.originalDelegate = self.interactivePopGestureRecognizer.delegate;
    self.interactivePopGestureRecognizer.delegate = self.interactivePopGestureDelegate;
}

@end
Timur Bernikovich
fuente
3
¡Porque ObjC aún no ha muerto! 😉
MonsieurDart
2
Ésta es la solución correcta. Cualquier otra solución que no reenvíe al delegado original es incorrecta.
Josh Bernfeld
6

Mi solución es extender directamente la UINavigationControllerclase:

import UIKit

extension UINavigationController: UIGestureRecognizerDelegate {

    override open func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        self.interactivePopGestureRecognizer?.delegate = self
    }

    public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return self.viewControllers.count > 1
    }

}

De esta forma, todos los controladores de navegación se descartarán deslizándolos.

fredericdnd
fuente
Curiosamente, esto está provocando viewDidAppearque se ignoren todas las llamadas en los VC que pertenecen a cualquier controlador de navegación.
Cumanzor
4

Puede hacerlo con un Delegado Proxy. Cuando esté construyendo el controlador de navegación, tome el delegado existente. Y páselo al proxy. Luego, pase todos los métodos de delegado al delegado existente, excepto el gestureRecognizer:shouldReceiveTouch:usoforwardingTargetForSelector:

Preparar:

let vc = UIViewController(nibName: nil, bundle: nil)
let navVC = UINavigationController(rootViewController: vc)
let bridgingDelegate = ProxyDelegate()
bridgingDelegate.existingDelegate = navVC.interactivePopGestureRecognizer?.delegate
navVC.interactivePopGestureRecognizer?.delegate = bridgingDelegate

Delegado apoderado:

class ProxyDelegate: NSObject, UIGestureRecognizerDelegate {
    var existingDelegate: UIGestureRecognizerDelegate? = nil

    override func forwardingTargetForSelector(aSelector: Selector) -> AnyObject? {
        return existingDelegate
    }

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
        return true
    }  
}
Nathan Perry
fuente
¡Esta respuesta es verdadero estilo Obj-C!
Sound Blaster
forwardingTargetForSelector me habría ahorrado tanto tiempo en un proyecto anterior si lo hubiera sabido. ¡Buen material!
VaporwareWolf
4

La respuesta de Hunter Monk es realmente asombrosa, pero desafortunadamente en iOS 13.3.1, no funciona.

Te explicare otra forma de esconderte UINavigationBary no perderswipe to back gesture . He probado en iOS 13.3.1 y 12.4.3 y funciona.

Necesita crear una clase personalizada de UINavigationControllery configurar esa clase para UINavigationControllerenStoryboard

Establezca la clase personalizada en <code> UINavigationController </code>

NO esconda el NavigationBaren elStoryboard

<code> UINavigationController </code> Inspector de atributos:

Ejemplo de Storyboard:

Guión gráfico:

Y finalmente, pon esto: navigationBar.isHidden = trueen viewDidLoaddeCustomNavigationController clase.

Asegúrese de NO utilizar este método setNavigationBarHidden(true, animated: true)para ocultar el NavigationBar.

import UIKit

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationBar.isHidden = true
    }
}
Jusuf Saiti
fuente
2
He probado esto en un dispositivo real iPhone 6S Plus con iOS 13.4.1 y deslizar hacia atrás funciona.
Emre Aydin
1
también funciona en iOS 14.0.1 más reciente
bezoadam
1

Respuesta de Xamarin:

Implemente la IUIGestureRecognizerDelegateinterfaz en la definición de clase de su ViewController:

public partial class myViewController : UIViewController, IUIGestureRecognizerDelegate

En su ViewController agregue el siguiente método:

[Export("gestureRecognizerShouldBegin:")]
public bool ShouldBegin(UIGestureRecognizer recognizer) {
  if (recognizer is UIScreenEdgePanGestureRecognizer && 
      NavigationController.ViewControllers.Length == 1) {
    return false;
  }
  return true;
}

En su ViewController's ViewDidLoad() agregue la siguiente línea:

NavigationController.InteractivePopGestureRecognizer.Delegate = this;
Ahmad
fuente
¿Es de suponer que esto está en el UINavigationControllercontrolador de vista raíz de? Me sale EXEC_BAD_ACCESScuando intento esto.
Benjohn
¿Puede desplazarse por los bordes en el controlador de vista raíz? Eso no debería ser posible porque cuando estás en el VC raíz, has eliminado todos los demás VC, y la longitud de la matriz de VC de tu Nav debería ser 1.
Ahmad
El bloqueo ocurre antes de la llamada a gestureRecognizerShouldBegin:.
Benjohn
1
¿Puede publicar su código de VC en una nueva pregunta o en foros de Xamarin?
Ahmad
No, no lo he hecho. ¡Creo que lo dejaré por .1!
Benjohn
1

Probé esto y está funcionando perfectamente: Cómo ocultar la barra de navegación sin perder la capacidad de deslizamiento

La idea es implementar "UIGestureRecognizerDelegate" en su .hy agregar esto a su archivo .m.

- (void)viewWillAppear:(BOOL)animated {
// hide nav bar
[[self navigationController] setNavigationBarHidden:YES animated:YES];

// enable slide-back
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
  }
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
   return YES;  
}
KarimIhab
fuente
1

Aquí está mi solución: estoy cambiando alfa en la barra de navegación, pero la barra de navegación no está oculta. Todos mis controladores de vista son una subclase de mi BaseViewController, y ahí tengo:

    override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    navigationController?.navigationBar.alpha = 0.0
}

También puede subclasificar UINavigationController y poner ese método allí.

Mladen Ivastinovic
fuente
0

Algunas personas han tenido éxito llamando al setNavigationBarHiddenmétodo con animated en su YESlugar.

Mundi
fuente
No probé suerte. Actualizando mi respuesta para cubrir esta sugerencia.
mihai
0

En mi controlador de vista sin barra de navegación utilizo

open override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)

  CATransaction.begin()
  UIView.animate(withDuration: 0.25, animations: { [weak self] in
    self?.navigationController?.navigationBar.alpha = 0.01
  })
  CATransaction.commit()
}

open override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)
  CATransaction.begin()
  UIView.animate(withDuration: 0.25, animations: { [weak self] in
    self?.navigationController?.navigationBar.alpha = 1.0
  })
  CATransaction.commit()
}

Sin embargo, durante el despido interactivo, el botón de retroceso brillará, por eso lo oculté.

codificador de frutas
fuente
-2

Hay una solución realmente simple que probé y funciona perfectamente, está en Xamarin.iOS pero también se puede aplicar al nativo:

    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
        this.NavigationController.SetNavigationBarHidden(true, true);
    }

    public override void ViewDidAppear(bool animated)
    {
        base.ViewDidAppear(animated);
        this.NavigationController.SetNavigationBarHidden(false, false);
        this.NavigationController.NavigationBar.Hidden = true;
    }

    public override void ViewWillDisappear(bool animated)
    {
        base.ViewWillDisappear(animated);
        this.NavigationController.SetNavigationBarHidden(true, false);
    }
João Palma
fuente
-6

Aquí se explica cómo deshabilitar el reconocedor de gestos cuando el usuario se desliza fuera del ViewController. Puede pegarlo en sus métodos viewWillAppear () o en sus métodos ViewDidLoad ().

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
Eddwin Paz
fuente
Lea la pregunta antes de publicar las respuestas. La pregunta era habilitarlo, no deshabilitarlo. AMAMOS EL GESTO POP.
Yogesh Maheshwari