Sem deslizar para trás ao ocultar a barra de navegação no UINavigationController


86

Eu amo o pacote de furto que é herdado da incorporação de suas visualizações em um UINavigationController. Infelizmente, não consigo encontrar uma maneira de ocultar o, NavigationBarmas ainda tenho o toque de deslizar para trás gesture. Posso escrever gestos personalizados, mas prefiro não fazê- UINavigationControllerlo e, em gesturevez disso, preferir deslizar para trás .

se eu desmarcar no storyboard, deslizar para trás não funciona

insira a descrição da imagem aqui

alternativamente, se eu ocultar programaticamente, o mesmo cenário.

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

Não há como ocultar a parte superior NavigationBare ainda deslizar?


1
A adição de um UIGestureRecognizer é aceitável? É uma brisa de implementar.
SwiftArchitect

1
@LancelotdelaMare, estava tentando evitar isso, pois não funcionará tão bem quanto deslizar para trás do UINavigationController. Estou olhando para UIScreenEdgePanGestureRecognizer, já que algumas pessoas dizem que ajuda, mas ainda não o fez funcionar. Procurando a solução mais simples e elegante aqui.
mihai

Respostas:


96

Um hack que está funcionando é definir o interactivePopGestureRecognizerdelegado de UINavigationControllerpara nilassim:

[self.navigationController.interactivePopGestureRecognizer setDelegate:nil];

Mas em algumas situações, pode criar efeitos estranhos.


16
"deslizar para trás repetidamente pode fazer com que o gesto seja reconhecido quando há apenas um controlador de visualização na pilha, o que, por sua vez, coloca uma IU em um estado (acho inesperado pelos engenheiros do UIKit) em que para de reconhecer quaisquer gestos"
HorseT

4
Uma alternativa que pode proteger contra esse estado inesperado seria defini-lo como um objeto de baixo nível (eu usei meu delegado app) e implementar gestureRecognizerShouldBegin, retornando truese o navigationController's viewControllercontagem é maior que 0.
Kenny Winker

4
Embora isso funcione, eu recomendo ALTAMENTE contra isso. Quebrar o delegado estava causando um bloqueio de thread principal raro e difícil de identificar. Acontece que não é um bloco de thread principal, mas é o que @HorseT descreveu.
Josh Bernfeld

3
Meu aplicativo salva o identificador de delegado e, em seguida, o restaura viewWillDisappeare, até agora, não experimentou nenhum efeito colateral adverso.
Don Park de

1
!!!! É altamente desencorajado usar esta solução, ao usar repetidamente o deslize, ocorre um comportamento estranho, a parte de trás é desativada e o aplicativo inteiro não responde mais
KarimIhab

79

Problemas com outros métodos

Configurando o interactivePopGestureRecognizer.delegate = nil tem efeitos colaterais indesejados.

A configuração navigationController?.navigationBar.hidden = truefunciona, mas não permite que sua alteração na barra de navegação seja ocultada.

Por último, geralmente é uma prática melhor criar um objeto de modelo que seja o UIGestureRecognizerDelegatepara seu controlador de navegação. Configurá-lo como um controlador na UINavigationControllerpilha é o que está causando os EXC_BAD_ACCESSerros.

Solução Completa

Primeiro, adicione esta classe ao seu projeto:

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

Em seguida, defina seu controlador de navegação interactivePopGestureRecognizer.delegatepara uma instância de sua nova InteractivePopRecognizerclasse.

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
}

Desfrute de uma barra de navegação oculta sem efeitos colaterais, que funciona mesmo se seu controlador superior tiver subvisualizações de tabela, coleção ou visualização de rolagem.


1
Ótima solução!
Matt Butler

1
A melhor resposta, obrigado!
Dory Daniel

2
@HunterMaximillionMonk obrigado pela ótima solução. Funciona
perfeitamente

1
@HunterMaximillionMonk isso parece funcionar corretamente, mas o problema com ele quando eu tenho vários controladores, depois de um tempo pop ele para de funcionar.
Premal Khetani

1
Definitivamente a melhor resposta!
dia

54

No meu caso, para evitar efeitos estranhos

Controlador de visualização raiz

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/


2
Às vezes recebo EXC_BAD_ACCESS ao usar isso
Andrey Gordeev

Para mim, não faz o gesto funcionar e frequentemente trava com oEXEC_BAD_ACCESS
Benjohn

2
Lembre-se de adicionar UIGestureRecognizerDelegateao controlador de exibição raiz ... No meu caso, o delegado foi definido como nulo em um controlador de exibição posterior do que o controlador de exibição raiz, portanto, quando retornou ao controlador de exibição raiz, gestureRecognizerShouldBeginnão foi chamado. Então eu coloquei o .delegate = selfno viewDidAppear(). Isso resolveu os estranhos efeitos no meu caso ... Saúde!
Wiingaard de

@AndreyGordeev Você poderia dar alguns detalhes sobre quando EXEC_BAD_ACCESSacontece?
Jaybo

Veja mais informações sobre o EXC_BAD_ACCESSerro: stackoverflow.com/questions/28746123/…
Andrey Gordeev

25

Atualizado para iOS 13.4

O iOS 13.4 quebrou a solução anterior, então as coisas vão ficar feias. Parece que no iOS 13.4 esse comportamento agora é controlado por um método privado _gestureRecognizer:shouldReceiveEvent:(não deve ser confundido com o novo shouldReceivemétodo público adicionado no iOS 13.4).


Descobri que outras soluções postadas substituindo o delegado ou definindo-o como nulo causaram algum comportamento inesperado.

No meu caso, quando eu estava no topo da pilha de navegação e tentava usar o gesto para abrir mais uma, ele falharia (como esperado), mas as tentativas subsequentes de empurrar para a pilha começariam a causar falhas gráficas estranhas no Barra de navegação. Isso faz sentido, porque o delegado está sendo usado para lidar com mais do que apenas bloquear ou não o gesto de ser reconhecido quando a barra de navegação está oculta e todos os outros comportamentos foram descartados.

Pelo meu teste, parece que gestureRecognizer(_:, shouldReceiveTouch:)é o método que o delegado original está implementando para bloquear o gesto de ser reconhecido quando a barra de navegação está oculta, não gestureRecognizerShouldBegin(_:). Outras soluções que implementam gestureRecognizerShouldBegin(_:)em seus delegados funcionam porque a falta de uma implementação degestureRecognizer(_:, shouldReceiveTouch:) causará o comportamento padrão de receber todos os toques.

A solução de @Nathan Perry chega perto, mas sem uma implementação respondsToSelector(_:), o código UIKit que envia mensagens para o delegado acreditará que não há implementação para nenhum dos outros métodos delegados e forwardingTargetForSelector(_:)nunca será chamado.

Portanto, assumimos o controle de `gestorRecognizer (_ :, deveriaReceberTouch :) em um cenário específico que desejamos modificar o comportamento e, caso contrário, encaminharemos todo o resto para o 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
        }
    }
}

1
Parece que sua solução é a melhor para o momento. Obrigado!
Timur Bernikovich

"mas as tentativas subsequentes de empurrar para a pilha começariam a causar falhas gráficas estranhas na barra de navegação" - estou confuso aqui. Achei que não tínhamos barra de navegação? Essa é a questão? Na minha situação, tenho um controlador de navegação embutido como um controlador de visualização filho sem navbar; o VC que o contém tem os controles de navegação. Então, deixei o VC contido ser o delegado do reconhecedor e simplesmente fiz a gestureRecognizerShouldBegin:coisa, e "parece funcionar". Me perguntando se eu deveria cuidar.
skagedal

2
navigationControllerOcorreu um vazamento de memória, pois era uma referência forte no AlwaysPoppableDelegate. Eu editei o código para fazer disso uma weakreferência.
Graham Perks

3
Esta boa solução não funciona mais no iOS 13.4
Ely

@ChrisVasselli Realmente incrível, obrigado! Esperançosamente, isso será aprovado na verificação de métodos privados da análise da App Store.
Ely

16

Você pode criar uma subclasse de UINavigationController da seguinte forma:

@interface CustomNavigationController : UINavigationController<UIGestureRecognizerDelegate>

@end

Implementação:

@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

2
Usar essa abordagem é quebrar o gesto pop em UIPageViewControlleroverscroll.
atulkhatri

Descobri que viewController.count> 1 verificação é necessária. Se o usuário tentar deslizar de volta apenas com o VC raiz, a IU travará no próximo envio de VC.
VaporwareWolf

11

Resposta simples, sem efeito colateral

Embora a maioria das respostas aqui sejam boas, elas aparentemente têm efeitos colaterais indesejados (quebra de aplicativo) ou são prolixas.

A solução mais simples, porém funcional, que consegui propor foi a seguinte:

No ViewController em que você está ocultando a barra de navegação,

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

Outras respostas sugeriram simplesmente definir o delegado como zero. Deslizar para trás para o controlador de visualização inicial na pilha de navegação resulta na desativação de todos os gestos. Algum tipo de descuido, talvez, dos desenvolvedores de UIKit / UIGesture.

Além disso, algumas respostas aqui que implementei resultaram em um comportamento de navegação fora do padrão da apple (especificamente, permitindo a capacidade de rolar para cima ou para baixo enquanto deslize para trás). Essas respostas também parecem um pouco prolixas e, em alguns casos, incompletas.


viewDidLoad()não é um bom lugar para capturar, initialInteractivePopGestureRecognizerDelegatepois navigationControllerpode haver nulo (ainda não colocado na pilha). viewWillAppeardo lugar onde você está escondendo a barra de navegação seria mais apropriado
nCod3d

10

Com base na resposta de Hunter Maximillion Monk , criei uma subclasse para UINavigationController e, em seguida, configurei a classe personalizada para meu UINavigationController em meu storyboard. O código final para as duas classes se parece com este:

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

Storyboard:

Classe personalizada do controlador de navegação storyboard


8

Parece que a solução fornecida por @ChrisVasseli é a melhor. Eu gostaria de fornecer a mesma solução em Objective-C porque a questão é sobre Objective-C (veja as tags)

@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

3
Porque ObjC ainda não morreu! 😉
MonsieurDart

2
Esta é a solução correta. Qualquer outra solução que não encaminhe para o delegado original está incorreta.
Josh Bernfeld

6

Minha solução é estender a UINavigationControllerclasse diretamente :

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
    }

}

Dessa forma, todos os controladores de navegação poderão ser dispensados ​​deslizando-se.


Estranhamente, isso está fazendo com que todas as viewDidAppearchamadas nos VCs pertencentes a qualquer controlador de navegação sejam ignoradas.
cumanzor

4

Você pode fazer isso com um delegado proxy. Quando você estiver construindo o controlador de navegação, pegue o delegado existente. E passe para o proxy. Em seguida, passe todos os métodos de delegado para o delegado existente, exceto gestureRecognizer:shouldReceiveTouch:usandoforwardingTargetForSelector:

Configuração:

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 Proxy:

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

Esta resposta é o verdadeiro estilo Obj-C!
Sound Blaster

forwardingTargetForSelector teria me poupado muito tempo em um projeto anterior se eu soubesse sobre ele. Coisa boa!
VaporwareWolf

4

A resposta de Hunter Monk é realmente incrível, mas infelizmente no iOS 13.3.1, ela não funciona.

Vou explicar outra forma de se esconder UINavigationBare não perder swipe to back gesture. Eu testei no iOS 13.3.1 e 12.4.3 e funciona.

Você precisa criar uma classe personalizada UINavigationControllere definir essa classe para UINavigationControlleremStoryboard

Defina a classe personalizada para <code> UINavigationController </code>

NÃO esconda o NavigationBarnoStoryboard

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

Exemplo em Storyboard:

Storyboard:

E, finalmente, coloque o seguinte: navigationBar.isHidden = trueem sala viewDidLoadde CustomNavigationControlleraula.

Certifique-se de NÃO usar este método setNavigationBarHidden(true, animated: true)para ocultar o NavigationBar.

import UIKit

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationBar.isHidden = true
    }
}

2
Eu testei isso em um dispositivo real iPhone 6S Plus com iOS 13.4.1e retrocesso funciona.
Emre Aydin

1
funciona também no iOS 14.0.1 mais recente
bezoadam

1

Resposta de Xamarin:

Implemente a IUIGestureRecognizerDelegateinterface na definição de classe do seu ViewController:

public partial class myViewController : UIViewController, IUIGestureRecognizerDelegate

Em seu ViewController, adicione o seguinte método:

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

No seu ViewController, ViewDidLoad()adicione a seguinte linha:

NavigationController.InteractivePopGestureRecognizer.Delegate = this;

Presumivelmente, isso está no UINavigationControllercontrolador de exibição de raiz do? Eu entendo EXEC_BAD_ACCESSquando tento isso.
Benjohn

Você é capaz de deslocar a borda no controlador de visualização raiz? Isso não deveria ser possível porque quando você está no VC raiz, você removeu todos os outros VCs, e o comprimento da matriz VC do seu Nav deve ser 1.
Ahmad

A falha ocorre antes da chamada para gestureRecognizerShouldBegin:.
Benjohn

1
Você pode postar seu código VC em uma nova pergunta ou nos fóruns do Xamarin?
Ahmad

Não, eu não. Acho que vou deixar por 0,1!
Benjohn 01 de

1

Eu tentei isso e está funcionando perfeitamente: Como ocultar a barra de navegação sem perder a capacidade de deslizar para trás

A ideia é implementar "UIGestureRecognizerDelegate" em seu .h e adicioná-lo ao seu arquivo .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;  
}

1

Aqui está minha solução: estou alterando o alfa na barra de navegação, mas a barra de navegação não está oculta. Todos os meus controladores de visualização são uma subclasse do meu BaseViewController, e aí eu tenho:

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

Você também pode criar uma subclasse de UINavigationController e colocar esse método lá.


0

Algumas pessoas tiveram sucesso ao chamar o setNavigationBarHiddenmétodo de animado YES.


Não tentei sorte. Atualizando minha resposta para cobrir esta sugestão.
mihai

0

Na minha visão, controlador sem barra de navegação, eu uso

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

No entanto, durante a dispensa interativa, o botão Voltar irá brilhar, e é por isso que o escondi.


-2

Existe uma solução realmente simples que experimentei e funciona perfeitamente, está no Xamarin.iOS, mas também pode ser aplicada ao 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);
    }

-6

Aqui está como desativar o reconhecedor de gestos quando o usuário desliza para fora do ViewController. Você pode colá-lo em seus métodos viewWillAppear () ou ViewDidLoad ().

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

Por favor, leia a pergunta antes de postar respostas. A questão era ativá-lo, não desativá-lo. NÓS AMAMOS O GESTO POP.
Yogesh Maheshwari
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.