Comecei a usar o Xcode 4.5 e recebi esse erro no console:
Aviso: Tente apresentar <finishViewController: 0x1e56e0a0> em <ViewController: 0x1ec3e000> cuja exibição não está na hierarquia da janela!
A visualização ainda está sendo apresentada e tudo no aplicativo está funcionando bem. Isso é algo novo no iOS 6?
Este é o código que estou usando para alternar entre visualizações:
UIStoryboard *storyboard = self.storyboard;
finishViewController *finished =
[storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];
[self presentViewController:finished animated:NO completion:NULL];
presentViewController:animated:completion
um controlador nav. Você está fazendo isso no delegado do aplicativo?Respostas:
De onde você está chamando esse método? Eu tive um problema em que estava tentando apresentar um controlador de exibição modal dentro do
viewDidLoad
método. A solução para mim foi passar esta chamada para oviewDidAppear:
métodoMinha presunção é que a visualização do controlador de exibição não esteja na hierarquia da janela no ponto em que foi carregada (quando a
viewDidLoad
mensagem é enviada), mas está na hierarquia da janela após a apresentação (quando aviewDidAppear:
mensagem é enviada) .Cuidado
Se você fizer uma chamada
presentViewController:animated:completion:
noviewDidAppear:
você pode executar em um problema no qual o controlador de vista modal está sempre sendo apresentados sempre View aparece do controlador de vista (o que faz sentido!) E assim o controlador de vista modal sendo apresentada nunca vai embora .. .Talvez este não seja o melhor local para apresentar o controlador de exibição modal ou talvez seja necessário manter algum estado adicional que permita ao controlador de exibição decidir se deve ou não apresentar o controlador de exibição modal imediatamente.
fonte
Outra causa potencial:
Eu tive esse problema ao apresentar acidentalmente o mesmo controlador de exibição duas vezes. (Uma vez com a
performSegueWithIdentifer:sender:
qual foi chamado quando o botão foi pressionado e uma segunda vez com um segue conectado diretamente ao botão).Efetivamente, dois segues foram disparados ao mesmo tempo e recebi o erro:
Attempt to present X on Y whose view is not in the window hierarchy!
fonte
present(viewController, animated: true, completion: nil)
dentro de um loop.viewWillLayoutSubviews
eviewDidLayoutSubviews
(iOS 5.0 ou superior) pode ser usado para esse fim. Eles são chamados mais cedo que viewDidAppear.fonte
Para Exibir qualquer subvisão para a visualização principal, use o seguinte código
Para ignorar qualquer subview da vista principal, use o seguinte código
fonte
Eu também encontrei este problema quando tentei apresentar um
UIViewController
noviewDidLoad
. A resposta de James Bedford funcionou, mas meu aplicativo mostrou os antecedentes primeiro por 1 ou 2 segundos.Após algumas pesquisas, encontrei uma maneira de resolver isso usando o
addChildViewController
.fonte
Provavelmente, como eu, você tem uma raiz errada
viewController
Eu quero exibir um
ViewController
em umnon-UIViewController
contexto,Portanto, não posso usar esse código:
Então, eu recebo um UIViewController:
Por alguma razão (bug lógico),
rootViewController
é algo diferente do esperado (normalUIViewController
). Corrijo o bug, substituindo-orootViewController
por umUINavigationController
, e o problema se foi.fonte
TL; DR Você pode ter apenas 1 rootViewController e é o mais recente apresentado. Portanto, não tente que um viewcontroller apresente outro viewcontroller quando ele já tiver apresentado um que não tenha sido descartado.
Depois de fazer alguns dos meus próprios testes, cheguei a uma conclusão.
Se você tiver um rootViewController que deseja apresentar tudo, poderá encontrar esse problema.
Aqui está o meu código rootController (aberto é o meu atalho para apresentar um viewcontroller a partir da raiz).
Se eu abrir aberto duas vezes seguidas (independentemente do tempo decorrido), isso funcionará bem na primeira abertura, mas NÃO na segunda abertura. A segunda tentativa aberta resultará no erro acima.
No entanto, se eu fechar a visualização apresentada mais recentemente e depois abrir, ela funcionará bem quando eu abrir novamente (em outro controlador de exibição).
O que concluí é que o rootViewController apenas da MOST-RECENT-CALL está na Hierarquia da exibição (mesmo que você não a tenha descartado ou removido uma exibição). Tentei jogar com todas as chamadas do carregador (viewDidLoad, viewDidAppear e fazer chamadas de despacho atrasadas) e descobri que a única maneira de fazê-lo funcionar é SOMENTE chamando presente do controlador de exibição mais superior.
fonte
wait
wait
decide
push screen to front
e é IMPOSSÍVEL o IOS ????Meu problema foi que eu estava realizando o segue em
UIApplicationDelegate
'sdidFinishLaunchingWithOptions
método antes eu ligueimakeKeyAndVisible()
na janela.fonte
Na minha situação, não pude colocar o meu em uma substituição de classe. Então, aqui está o que eu tenho:
fonte
Eu tive o mesmo problema. Eu tive que incorporar um controlador de navegação e apresentá-lo através dele. Abaixo está o código de exemplo.
fonte
Se você possui um objeto AVPlayer com o vídeo reproduzido, é necessário pausar o vídeo primeiro.
fonte
Eu tive o mesmo problema. O problema era que o performSegueWithIdentifier foi acionado por uma notificação, assim que eu coloquei a notificação no thread principal, a mensagem de aviso desapareceu.
fonte
Está funcionando bem, tente isso. Ligação
fonte
Caso isso ajude alguém, meu problema foi extremamente tolo. Totalmente minha culpa, é claro. Uma notificação estava acionando um método que estava chamando o modal. Mas eu não estava removendo a notificação corretamente, então, em algum momento, eu teria mais de uma notificação, para que o modal fosse chamado várias vezes. Obviamente, depois que você chama o modal uma vez, o controlador de exibição que o chama não está mais na hierarquia de visualizações, é por isso que vemos esse problema. Minha situação também causou muitos outros problemas, como seria de esperar.
Então, para resumir, o que você estiver fazendo, verifique se o modal não está sendo chamado mais de uma vez .
fonte
Acabei com um código que finalmente funciona para mim (Swift), considerando que você deseja exibir alguns
viewController
de praticamente qualquer lugar. Esse código obviamente travará quando não houver rootViewController disponível, esse é o final aberto. Também não inclui a mudança geralmente necessária para o thread da interface do usuário usandofonte
Este tipo de aviso pode significar que você está tentando apresentar novas
View Controller
atravésNavigation Controller
enquanto esteNavigation Controller
está atualmente apresentando outraView Controller
. Para corrigi-lo Você deve descartar o que é apresentado atualmenteView Controller
no início e, após a conclusão, apresentar o novo. Outra causa do aviso pode estar tentando apresentarView Controller
no thread outro que nãomain
.fonte
Eu tive um problema semelhante no Swift 4.2, mas minha visão não foi apresentada no ciclo de visualização. Eu descobri que tinha vários seguimentos a serem apresentados ao mesmo tempo. Então eu usei dispatchAsyncAfter.
fonte
Corrigi-o movendo a
start()
função dentro dodismiss
bloco de conclusão:O Start contém duas chamadas para
self.present()
uma para um UINavigationController e outra para umaUIImagePickerController
.Isso consertou para mim.
fonte
Você também pode receber esse aviso ao executar uma sequência de um controlador de exibição incorporado em um contêiner. A solução correta é usar segue do pai do contêiner, não do controlador de exibição do contêiner.
fonte
Tem que escrever abaixo da linha.
ao invés de
em UIViewController
fonte
Com Swift 3 ...
Outra causa possível para isso, que aconteceu comigo, foi passar de um tableViewCell para outro ViewController no Storyboard. Eu também usei
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {}
quando a célula foi clicada.Corrigi esse problema fazendo um segue do ViewController para o ViewController.
fonte
Eu tive esse problema e a causa principal foi assinar um manipulador de cliques de botão (TouchUpInside) várias vezes.
Ele estava assinando o ViewWillAppear, que estava sendo chamado várias vezes desde que adicionamos navegação para ir para outro controlador e, em seguida, voltamos a ele.
fonte
Aconteceu-me que as instruções no storyboard estavam meio que quebradas . A exclusão do segue (e a criação exata do mesmo segue novamente) resolveu o problema.
fonte
Com sua janela principal, sempre haverá momentos com transições incompatíveis com a apresentação de um alerta. Para permitir a apresentação de alertas a qualquer momento no ciclo de vida do aplicativo, você deve ter uma janela separada para fazer o trabalho.
Uso básico que, por design, sempre terá êxito:
fonte
Infelizmente, a solução aceita não funcionou no meu caso. Eu estava tentando navegar para um novo View Controller logo após relaxar de outro View Controller.
Encontrei uma solução usando um sinalizador para indicar qual segue de desenrolar foi chamado.
Em seguida, apresente o VC desejado com
present(_ viewControllerToPresent: UIViewController)
Basicamente, o código acima me permite capturar o desenrolar do login / SignUp VC e navegar até o painel, ou capturar a ação desenrolar do esquecer a senha VC e navegar para a página de login.
fonte
Corrigi este erro com o armazenamento da maioria dos controladores de visualização em constante, que é encontrada durante o ciclo sobre o rootViewController:
fonte
Descobri que esse bug chegou após a atualização do Xcode, acredito no Swift 5 . O problema estava acontecendo quando eu iniciei um segue programaticamente diretamente após desenrolar um controlador de exibição.
A solução chegou ao consertar um bug relacionado, que é que o usuário agora conseguia descontrair os seguidores deslizando a página para baixo. Isso quebrou a lógica do meu programa.
Foi corrigido alterando o modo Apresentação em todos os controladores de exibição de Automático para Tela inteira .
Você pode fazer isso no painel de atributos no construtor de interfaces. Ou veja esta resposta para saber como fazê-lo programaticamente.
fonte
Eu também tinha esse problema, mas não tinha nada a ver com o tempo. Eu estava usando um singleton para lidar com cenas, e o defini como apresentador. Em outras palavras, o "eu" não estava ligado a nada. Acabei de fazer da sua "cena" interior o novo apresentador e pronto, funcionou. (Voila perde o toque depois que você aprende o significado, heh).
Então, sim, não se trata de "encontrar magicamente o caminho certo", é entender como o seu código está e o que está fazendo. Estou feliz que a Apple tenha transmitido uma mensagem de aviso em inglês tão claro, mesmo com emoção. Parabéns ao desenvolvedor da apple que fez isso !!
fonte
Se outras soluções não parecerem boas por algum motivo, você ainda pode usar esse bom e velho
workaround
apresentar com o atraso 0, assim:Embora eu não tenha visto nenhuma garantia documentada de que seu VC estaria na hierarquia de exibição no horário em que o bloco de despacho está agendado para execução, observei que ele funcionaria perfeitamente.
Usar atraso de, por exemplo, 0,2 s também é uma opção. E a melhor coisa - dessa forma, você não precisa mexer com a variável booleana
viewDidAppear:
fonte
Isso funciona para apresentar qualquer controlador de exibição, se você tiver um controlador de navegação disponível. self.navigationController? .present (MyViewController, animado: true, conclusão: nil) Além disso, também posso apresentar alertas e controlador de correio.
fonte