Estou tentando substituir a ação padrão do botão Voltar em um controlador de navegação. Forneci ao alvo uma ação no botão personalizado. O estranho é que, ao atribuí-lo, o atributo backbutton não presta atenção a eles e apenas exibe a visualização atual e volta à raiz:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle: @"Servers"
style:UIBarButtonItemStylePlain
target:self
action:@selector(home)];
self.navigationItem.backBarButtonItem = backButton;
Assim que eu defini-lo através do leftBarButtonItem
sobre o navigationItem
que chama de minha ação, no entanto, em seguida, o botão se parece com uma simples rodada em vez do arrowed volta um:
self.navigationItem.leftBarButtonItem = backButton;
Como posso chamar a minha ação personalizada antes de voltar à visualização raiz? Existe uma maneira de substituir a ação de retorno padrão ou existe um método que sempre é chamado ao sair de uma exibição ( viewDidUnload
não faz isso)?
Respostas:
Tente colocar isso no controlador de exibição em que deseja detectar a impressora:
fonte
if (find(self.navigationController!.viewControllers as! [UIViewController],self)==nil)
Eu implementei a extensão UIViewController-BackButtonHandler . Ele não precisa subclassificar nada, basta colocá-lo em seu projeto e substituir o
navigationShouldPopOnBackButton
método naUIViewController
classe:Baixe o aplicativo de exemplo .
fonte
navigationBar:shouldPopItem:
método não é privado, pois faz parte doUINavigationBarDelegate
protocolo.YES
)? ou será no futuro? subclassificação é provavelmente uma opção mais seguraNO
o botão voltar permanece em um estado desativado (visualmente, porque ele ainda recebe e reage a eventos de toque). Eu trabalhei em torno disso adicionando umaelse
declaração àshouldPop
verificação e percorrendo as subvisões da barra de navegação e configurando oalpha
valor de volta para 1, se necessário, dentro de um bloco de animação: gist.github.com/idevsoftware/9754057Ao contrário de Amagrammer disse, é possível. Você precisa subclassificar o seu
navigationController
. Expliquei tudo aqui (incluindo código de exemplo).fonte
Versão rápida:
(de https://stackoverflow.com/a/19132881/826435 )
No seu controlador de exibição, você apenas se conforma a um protocolo e executa a ação que precisar:
Em seguida, crie uma classe, digamos
NavigationController+BackButton
, e copie e cole o código abaixo:fonte
shouldPopOnBackButtonPress
deve ser chamado desde que não haja bugs.performSomeActionOnThePressOfABackButton
é apenas um método inventado que não existe.performSomeActionOnThePressOfABackButton
no meu controlador para executar uma ação específica quando o botão Voltar é pressionado, mas esse método nunca foi chamado, a ação é um retorno de volta normaisUINavigationController
, onavigationBar.delegate
é definido como o controlador de navegação. Portanto, os métodos devem ser chamados. No entanto, em Swift, não consigo que eles sejam chamados, mesmo em uma subclasse. No entanto, consegui que eles fossem chamados no Objective-C, então eu usaria a versão do Objective-C por enquanto. Pode ser um bug rápido.Não é possível fazer diretamente. Existem algumas alternativas:
UIBarButtonItem
que valida ao tocar e aparecer se o teste for aprovadoUITextField
método delegado, como-textFieldShouldReturn:
, que é chamado depois que o botãoReturn
ouDone
é pressionado no tecladoA desvantagem da primeira opção é que o estilo da seta para a esquerda do botão Voltar não pode ser acessado a partir de um botão da barra personalizada. Então você tem que usar uma imagem ou usar um botão de estilo regular.
A segunda opção é boa porque você recebe o campo de texto de volta no método delegado, para que você possa direcionar sua lógica de validação para o campo de texto específico enviado ao método de retorno de chamada delegado.
fonte
Por algumas razões de segmentação, a solução mencionada por @HansPinckaers não era certa para mim, mas achei uma maneira muito mais fácil de tocar no botão Voltar, e quero colocar isso aqui, caso isso possa evitar horas de decepções para alguém. O truque é realmente fácil: basta adicionar um UIButton transparente como uma subview à sua UINavigationBar e definir seus seletores para ele como se fosse o botão real! Aqui está um exemplo usando o Monotouch e C #, mas a tradução para o objetivo-c não deve ser muito difícil de encontrar.
Curiosidade: para fins de teste e para encontrar boas dimensões para o meu botão falso, defino a cor de fundo como azul ... E aparece atrás do botão voltar! De qualquer forma, ele ainda captura qualquer toque direcionado ao botão original.
fonte
Essa técnica permite alterar o texto do botão "voltar" sem afetar o título de qualquer um dos controladores de exibição ou ver o texto do botão voltar mudar durante a animação.
Adicione isso ao método init no controlador de exibição de chamada :
fonte
Caminho mais fácil
Você pode usar os métodos de delegação do UINavigationController. O método
willShowViewController
é chamado quando o botão voltar do seu VC é pressionado. Faça o que quiser quando voltar btn pressionadofonte
Aqui está a minha solução Swift. Na sua subclasse de UIViewController, substitua o método navigationShouldPopOnBackButton.
fonte
Encontrei uma solução que também mantém o estilo do botão Voltar. Adicione o seguinte método ao seu controlador de exibição.
Agora forneça uma funcionalidade conforme necessário no seguinte método:
Tudo o que faz é cobrir o botão Voltar com um botão transparente;)
fonte
========================================
Com base em respostas anteriores com uialert em Swift5 em um assíncrono maneira
No seu controlador
fonte
Não acredito que isso seja possível, facilmente. A única maneira que eu acredito para contornar isso é criar sua própria imagem de seta do botão Voltar para colocar lá em cima. Foi frustrante para mim no começo, mas vejo por que, por uma questão de consistência, foi deixado de fora.
Você pode se aproximar (sem a seta) criando um botão regular e ocultando o botão voltar padrão:
fonte
Há uma maneira mais fácil por apenas subclasse o método delegado do
UINavigationBar
e substituir oShouldPopItem
método .fonte
De acordo com os documentos oficiais da Apple, https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html , devemos evitar isso.
"Se o nome de um método declarado em uma categoria for o mesmo que um método na classe original, ou um método em outra categoria na mesma classe (ou mesmo em uma superclasse), o comportamento será indefinido quanto à implementação de método usada em tempo de execução. É menos provável que isso seja um problema se você estiver usando categorias com suas próprias classes, mas pode causar problemas ao usar categorias para adicionar métodos às classes padrão Cocoa ou Cocoa Touch ".
fonte
Usando Swift:
fonte
Aqui está a versão Swift 3 da resposta do @oneway para capturar o evento do botão voltar da barra de navegação antes de ser acionado. Como
UINavigationBarDelegate
não pode ser usadoUIViewController
, você precisa criar um delegado que será acionado quandonavigationBar
shouldPop
for chamado.E então, no seu controlador de exibição, adicione a função delegar:
Percebi que muitas vezes queremos adicionar um controlador de alerta para que os usuários decidam se desejam voltar. Se assim for, você pode sempre
return false
emnavigationShouldPopOnBackButton()
função e fechar o controlador de vista, fazendo algo parecido com isto:fonte
Value of type 'UIViewController' has no member 'navigationShouldPopOnBackButton'
quando tento compilar seu código, para a linhaif vc.responds(to: #selector(v...
Além disso, oself.topViewController
retorna um opcional e há um aviso para isso também.let vc = self.topViewController as! MyViewController
e parece funcionar bem até agora. Se você acredita que é uma alteração correta, você pode editar o código. Além disso, se você acha que isso não deve ser feito, ficarei feliz em saber o porquê. Obrigado por este código. Você provavelmente deve escrever um post sobre isso, pois esta resposta está oculta conforme os votos.MyViewController
pode não estar em conformidadeBackButtonDelegate
. Em vez de forçar a desembrulhar, você deve fazerguard let vc = self.topViewController as? MyViewController else { return true }
para evitar uma possível falha.guard let vc = self.topViewController as? MyViewController else { self.popViewController(animated: true) return true }
para garantir que a tela esteja se movendo para a página certa, caso não possa ser projetada corretamente. Entendo agora que anavigationBar
função é chamada em todos os VCs e não apenas no viewcontroller em que esse código existe. Pode ser bom atualizar também o código na sua resposta? Obrigado.Versão Swift 4 iOS 11.3:
Isso se baseia na resposta de kgaidis em https://stackoverflow.com/a/34343418/4316579
Não tenho certeza de quando a extensão parou de funcionar, mas no momento em que escrevemos (Swift 4), parece que a extensão não será mais executada, a menos que você declare a conformidade com o UINavigationBarDelegate, conforme descrito abaixo.
Espero que isso ajude as pessoas que estão se perguntando por que sua extensão não funciona mais.
fonte
Usando as variáveis de destino e ação que você está deixando no momento 'nil', você poderá conectar suas caixas de diálogo de salvamento para que sejam chamadas quando o botão for "selecionado". Cuidado, isso pode ser acionado em momentos estranhos.
Concordo principalmente com o Amagrammer, mas não acho que seria tão difícil fazer o botão com a seta personalizada. Gostaria apenas de mudar o nome do botão Voltar, tirar uma captura de tela, fazer o photoshop do tamanho necessário e ter essa imagem na parte superior do botão.
fonte
Você pode tentar acessar o item do botão direito NavigationBars e definir sua propriedade seletora ... aqui está uma referência UIBarButtonItem , outra coisa, se isso não funcionar, o que definirá o trabalho, configure o item do botão direito da barra de navegação para um UIBarButtonItem personalizado que você criar e definir seu seletor ... espero que isso ajude
fonte
Para um formulário que exija entrada do usuário como essa, eu recomendaria invocá-lo como um "modal" em vez de parte da sua pilha de navegação. Dessa forma, eles precisam cuidar dos negócios no formulário e validá-los e descartá-los usando um botão personalizado. Você pode até criar uma barra de navegação que tenha a mesma aparência do resto do seu aplicativo, mas que lhe dê mais controle.
fonte
Para interceptar o botão Voltar, basta cobri-lo com um UIControl transparente e interceptar os toques.
fonte
Pelo menos no Xcode 5, existe uma solução simples e muito boa (não perfeita). No IB, arraste um Item do botão Bar para fora do painel Utilitários e solte-o no lado esquerdo da barra de navegação, onde estaria o botão Voltar. Defina o rótulo como "Voltar". Você terá um botão de funcionamento que poderá vincular ao seu IBAction e fechar o seu viewController. Estou fazendo algum trabalho e, em seguida, acionando um desenrolar segue e funciona perfeitamente.
O que não é ideal é que esse botão não receba a seta <e não leve adiante o título anterior dos VCs, mas acho que isso pode ser gerenciado. Para meus propósitos, defino o novo botão Voltar como um botão "Concluído", para que seu objetivo seja claro.
Você também acaba com dois botões Voltar no navegador IB, mas é fácil rotulá-lo para maior clareza.
fonte
Rápido
fonte
Essa abordagem funcionou para mim (mas o botão "Voltar" não terá o sinal "<"):
fonte
Versão rápida da resposta de @ onegray
Agora, em qualquer controlador, apenas se conforme
RequestsNavigationPopVerification
e esse comportamento é adotado por padrão.fonte
Usar
isMovingFromParentViewController
fonte
viewDidDisappear
. Dessa forma, ele só será acionado quando a visualização desaparecer.A resposta de @William está correta, no entanto, se o usuário iniciar um gesto de deslizar para voltar, o
viewWillDisappear
método será chamado e aindaself
não estará na pilha de navegação (ou seja,self.navigationController.viewControllers
não conteráself
), mesmo que o deslize não foi concluído e o controlador de exibição não foi realmente exibido. Assim, a solução seria:Desative o gesto de deslizar para voltar
viewDidAppear
e permita apenas o uso do botão voltar usando:Ou simplesmente use
viewDidDisappear
, da seguinte maneira:fonte
A solução que encontrei até agora não é muito boa, mas funciona para mim. Tomando esta resposta , 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:
fonte
Foi encontrada uma nova maneira de fazer isso:
Objetivo-C
Rápido
fonte