Eu empurrei uma visualização no controlador de navegação e quando pressiono o botão Voltar, ela vai para a visualização anterior automaticamente. Quero fazer algumas coisas quando o botão Voltar é pressionado antes de tirar a visualização da pilha. Qual é a função de retorno de chamada do botão Voltar?
102
Respostas:
A resposta de William Jockusch resolve esse problema com um truque fácil.
fonte
Na minha opinião a melhor solução.
Mas só funciona com iOS5 +
fonte
provavelmente é melhor substituir o botão de fundo para que você possa manipular o evento antes que a visualização seja exibida para coisas como a confirmação do usuário.
em viewDidLoad crie um UIBarButtonItem e defina self.navigationItem.leftBarButtonItem para ele passando em um sel
Em seguida, você pode fazer coisas como acionar um UIAlertView para confirmar a ação e abrir o controlador de visualização, etc.
Ou, em vez de criar um novo botão de fundo, você pode obedecer aos métodos de delegado UINavigationController para realizar ações quando o botão Voltar é pressionado.
fonte
UINavigationControllerDelegate
não possui métodos que são chamados quando o botão Voltar é pressionado.Esta é a maneira correta de detectar isso.
esse método é chamado quando a visualização também é enviada. Portanto, verificar parent == nil é para retirar o controlador de visualização da pilha
fonte
Eu acabo com essas soluções. Conforme tocamos no botão Voltar, o método viewDidDisappear é chamado. podemos verificar chamando o seletor isMovingFromParentViewController que retorna verdadeiro. podemos passar os dados de volta (usando Delegate). Espero que isso ajude alguém.
fonte
[super viewDidDisappear:animated]
Talvez seja um pouco tarde, mas eu também queria o mesmo comportamento antes. E a solução que escolhi funciona muito bem em um dos aplicativos atualmente na App Store. Como não vi ninguém usar um método semelhante, gostaria de compartilhá-lo aqui. A desvantagem dessa solução é que ela requer subclasses
UINavigationController
. Embora usar o Método Swizzling possa ajudar a evitar isso, não fui tão longe.Portanto, o botão Voltar padrão é gerenciado por
UINavigationBar
. Quando um usuário toca no botão Voltar,UINavigationBar
pergunte a seu delegado se ele deve abrir a tampaUINavigationItem
chamandonavigationBar(_:shouldPop:)
.UINavigationController
realmente implementa isso, mas não declara publicamente que adotaUINavigationBarDelegate
(por quê !?). Para interceptar este evento, crie uma subclasse deUINavigationController
, declare sua conformidadeUINavigationBarDelegate
e implementenavigationBar(_:shouldPop:)
. Retornetrue
se o item de cima deve ser estourado. Retornefalse
se for para ficar.Existem dois problemas. A primeira é que você deve chamar a
UINavigationController
versão denavigationBar(_:shouldPop:)
em algum momento. MasUINavigationBarController
não declara publicamente que está em conformidade comUINavigationBarDelegate
, tentar chamá-lo resultará em um erro de tempo de compilação. A solução que escolhi é usar o tempo de execução Objective-C para obter a implementação diretamente e chamá-la. Por favor, me avise se alguém tiver uma solução melhor.O outro problema é que
navigationBar(_:shouldPop:)
é chamado primeiro segue porpopViewController(animated:)
se o usuário tocar no botão Voltar. A ordem é invertida se o controlador de visualização for acionado chamandopopViewController(animated:)
. Neste caso, utilizo um booleano para detectar sepopViewController(animated:)
é chamado antes, onavigationBar(_:shouldPop:)
que significa que o usuário pressionou o botão Voltar.Além disso, faço uma extensão de
UIViewController
para permitir que o controlador de navegação pergunte ao controlador de visualização se ele deve ser exibido se o usuário tocar no botão Voltar. Os controladores de visualização podem retornarfalse
e fazer quaisquer ações necessárias e chamarpopViewController(animated:)
mais tarde.E em você visualiza os controladores, implemente
shouldBePopped(_:)
. Se você não implementar este método, o comportamento padrão será abrir o controlador de visualização assim que o usuário tocar no botão Voltar, como de costume.Você pode ver minha demonstração aqui .
fonte
Para "ANTES de retirar a visualização da pilha":
fonte
Existe uma maneira mais apropriada do que perguntar aos viewControllers. Você pode tornar seu controlador um delegado da barra de navegação que possui o botão Voltar. Aqui está um exemplo. Na implementação do controlador em que você deseja lidar com o pressionamento do botão Voltar, diga que ele implementará o protocolo UINavigationBarDelegate:
Então, em algum lugar em seu código de inicialização (provavelmente em viewDidLoad) torne seu controlador o delegado de sua barra de navegação:
Finalmente, implemente o método shouldPopItem. Este método é chamado logo que o botão Voltar é pressionado. Se você tiver vários controladores ou itens de navegação na pilha, provavelmente desejará verificar quais desses itens de navegação estão sendo exibidos (o parâmetro do item), de modo que você só faça suas coisas personalizadas quando espera. Aqui está um exemplo:
fonte
Se você não puder usar "viewWillDisappear" ou método semelhante, tente criar uma subclasse de UINavigationController. Esta é a classe de cabeçalho:
Classe de implementação:
Por outro lado, você precisa vincular este viewController ao seu NavigationController personalizado, portanto, em seu método viewDidLoad para seu viewController regular, faça o seguinte:
fonte
Aqui está outra maneira que implementei (não testei com um segue de desenrolamento, mas provavelmente não iria diferenciar, como outros afirmaram em relação a outras soluções nesta página) para fazer com que o controlador de visualização pai execute ações antes do VC filho que ele empurrou é retirado da pilha de visualização (eu usei alguns níveis abaixo do UINavigationController original). Isso também pode ser usado para executar ações antes que o childVC seja enviado. Isso tem a vantagem de trabalhar com o botão Voltar do sistema iOS, em vez de criar um UIBarButtonItem ou UIButton personalizado.
Peça ao seu pai VC para adotar o
UINavigationControllerDelegate
protocolo e se registrar para mensagens delegadas:Implemente este
UINavigationControllerDelegate
método de instância emMyParentViewController
:Se você especificar uma função de retorno de chamada específica no
UINavigationControllerDelegate
método de instância acima}
fonte
Isso é o que funciona para mim no Swift:
fonte
Se você estiver usando um Storyboard e estiver vindo de um push segue, você também pode simplesmente substituir
shouldPerformSegueWithIdentifier:sender:
.fonte