Preciso executar algumas ações quando o botão voltar (retornar à tela anterior, retornar à visualização dos pais) é pressionado em uma barra de navegação.
Existe algum método que eu possa implementar para capturar o evento e acionar algumas ações para pausar e salvar dados antes que a tela desapareça?
iphone
objective-c
ios
xcode
ewok
fonte
fonte
Respostas:
ATUALIZAÇÃO: De acordo com alguns comentários, a solução na resposta original parece não funcionar em certos cenários no iOS 8+. Não posso verificar se esse é realmente o caso sem mais detalhes.
Para aqueles de vocês, porém, nessa situação, há uma alternativa. Detectar quando um controlador de exibição está sendo acionado é possível substituindo-o
willMove(toParentViewController:)
. A idéia básica é que um controlador de exibição esteja sendo acionado quandoparent
estivernil
.Confira "Implementando um Container View Controller" para obter mais detalhes.
Desde o iOS 5, descobri que a maneira mais fácil de lidar com essa situação é usar o novo método
- (BOOL)isMovingFromParentViewController
:- (BOOL)isMovingFromParentViewController
faz sentido quando você está pressionando e acionando controladores em uma pilha de navegação.No entanto, se você estiver apresentando controladores de exibição modal, use
- (BOOL)isBeingDismissed
:Conforme observado nesta pergunta , você pode combinar as duas propriedades:
Outras soluções dependem da existência de a
UINavigationBar
. Em vez disso, goste mais da minha abordagem, porque desacopla as tarefas necessárias a serem executadas da ação que acionou o evento, ou seja, pressionar o botão Voltar.fonte
self.isMovingFromParentViewController
tem valor TRUE quando estou exibindo a pilha de navegação programaticamente usandopopToRootViewControllerAnimated
- sem nenhum toque no botão voltar. Devo reduzir a sua resposta? (o sujeito diz "botão 'voltar' é pressionado em uma barra de navegação")override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParentViewController(){ println("back button pressed") } }
-viewDidDisappear:
uma vez que é possível que você vai ter um-viewWillDisappear:
sem-viewDidDisappear:
(como quando você começar passando para descartar um item de controlador de navegação e, em seguida, cancelar o furto.Enquanto
viewWillAppear()
eviewDidDisappear()
são chamados quando o botão Voltar é pressionado, eles também são chamados em outros momentos. Veja o final da resposta para mais informações.Usando UIViewController.parent
A detecção do botão Voltar é melhor quando o VC é removido do pai (o NavigationController) com a ajuda de
willMoveToParentViewController(_:)
OUdidMoveToParentViewController()
Se o pai for nulo, o controlador de exibição está sendo retirado da pilha de navegação e descartado. Se o pai não for nulo, ele será adicionado à pilha e apresentado.
Trocar
willMove
paradidMove
e verificação self.parent para fazer o trabalho após o controlador de vista é indeferido.Parando a dispensa
Observe que verificar o pai não permite "pausar" a transição se você precisar fazer algum tipo de salvamento assíncrono. Para fazer isso, você pode implementar o seguinte. A única desvantagem aqui é que você perde o elegante botão de estilo / animação do iOS. Também tenha cuidado aqui com o gesto de furto interativo. Use o seguinte para lidar com este caso.
Mais informações aparecerão / apareceram
Se você não conseguiu o
viewWillAppear
viewDidDisappear
problema, vamos dar um exemplo. Digamos que você tenha três controladores de exibição:Vamos seguir os exorta a
detailVC
que você vá dolistVC
parasettingsVC
e de volta paralistVC
Lista> Detalhe (push detailVC)
Detail.viewDidAppear
<- apareceDetail> Settings (push settingsVC)
Detail.viewDidDisappear
<- desapareceE à medida que voltamos ...
Configurações> Detalhe (pop settingsVC)
Detail.viewDidAppear
<- apareceDetalhes> List (pop detailVC)
Detail.viewDidDisappear
<- desapareceObserve que isso
viewDidDisappear
é chamado várias vezes, não apenas ao voltar, mas também ao avançar. Para uma operação rápida que pode ser desejada, mas para uma operação mais complexa como uma chamada de rede para salvar, talvez não.fonte
didMoveToParantViewController:
deve fazer o trabalho quando a visualização não estiver mais visível. Útil para iOS7 com o InteractiveGesutre_ = self.navigationController?.popViewController(animated: true)
, portanto, não é apenas chamado ao pressionar o botão Voltar. Estou procurando uma chamada que funcione apenas quando Voltar for pressionado.Primeiro método
Segundo método
fonte
Aqueles que afirmam que isso não funciona estão enganados:
Isso funciona bem. Então, o que está causando o mito generalizado de que não?
O problema parece ser devido a uma implementação incorreta de um método diferente , a saber, que a implementação do
willMove(toParent:)
esqueceu de chamarsuper
.Se você implementar
willMove(toParent:)
sem chamarsuper
,self.isMovingFromParent
seráfalse
e o uso deviewWillDisappear
parecerá falhar. Não falhou; você o quebrou.NOTA: O problema real é geralmente o segundo controlador de visualização que detecta que o primeiro controlador de visualização foi acionado. Veja também a discussão mais geral aqui: A detecção unificada do UIViewController "tornou-se a mais avançada"?
EDIT Um comentário sugere que isso deveria ser
viewDidDisappear
melhor queviewWillDisappear
.fonte
true
para o gesto de deslize interativo - a partir da borda esquerda do controlador de exibição - mesmo que o deslize não tenha sido totalmente deslocado. Então, em vez de fazer check-inwillDisappear
, fazê-lo emdidDisappear
obras.Estou brincando (ou lutando) com esse problema há dois dias. Na IMO, a melhor abordagem é apenas criar uma classe de extensão e um protocolo, como este:
Isso funciona porque
UINavigationController
receberá uma chamadanavigationBar:shouldPopItem:
sempre que um controlador de exibição for acionado. Detectamos se a tecla Voltar foi pressionada ou não (qualquer outro botão). A única coisa que você precisa fazer é implementar o protocolo no controlador de exibição em que a tecla Voltar é pressionada.Lembre-se de colocar manualmente o controlador de exibição dentro
backButtonPressedSel
, se estiver tudo bem.Se você já tiver subclassificado
UINavigationViewController
e implementadonavigationBar:shouldPopItem:
, não se preocupe, isso não interferirá.Você também pode estar interessado em desativar o gesto de volta.
fonte
Isso funciona para mim no iOS 9.3.x com Swift:
Ao contrário de outras soluções aqui, isso não parece desencadear inesperadamente.
fonte
Para o registro, acho que isso é mais do que ele estava procurando ...
fonte
Como
purrrminator
diz, a resposta porelitalon
não é totalmente correta, poisyour stuff
seria executada mesmo quando o controlador fosse acionado programaticamente.A solução que encontrei até agora não é muito boa, mas funciona para mim. Além do que foi
elitalon
dito, também verifico se estou aparecendo programaticamente ou não:Você precisa adicionar essa propriedade ao seu controlador e configurá-la como YES antes de aparecer programaticamente:
Obrigado pela ajuda!
fonte
A melhor maneira é usar os métodos de delegação UINavigationController
Usando isso, você pode saber qual controlador está mostrando o UINavigationController.
fonte
Resolvi esse problema adicionando um UIControl à barra de navegação no lado esquerdo.
E você precisa se lembrar de removê-lo quando o modo de exibição desaparecer:
Isso é tudo!
fonte
Você pode usar o retorno de chamada do botão voltar, assim:
para a versão rápida, você pode fazer algo como no escopo global
Abaixo, você coloca no viewcontroller onde deseja controlar a ação do botão Voltar:
fonte
navigationShouldPopOnBackButton
vem? Não faz parte da API pública.Como disse Coli88, você deve verificar o protocolo UINavigationBarDelegate.
De uma maneira mais geral, você também pode usar o
- (void)viewWillDisapear:(BOOL)animated
para executar um trabalho personalizado quando a visualização mantida pelo controlador de visualização atualmente visível estiver prestes a desaparecer. Infelizmente, isso abrangeria os casos push e pop.fonte
Para Swift com um UINavigationController:
fonte
A resposta do 7ynk3r foi muito próxima do que eu usei no final, mas precisava de alguns ajustes:
fonte
Você deve verificar o protocolo UINavigationBarDelegate . Nesse caso, convém usar o método navigationBar: shouldPopItem:.
fonte
self.navigationController.isMovingFromParentViewController não está mais funcionando no iOS8 e 9 eu uso:
fonte
(RÁPIDO)
solução finalmente encontrada. O método que procurávamos é "willShowViewController", que é o método delegado de UINavigationController
fonte
MyViewController
paraPushedController
.