A corrente UIViewController
na tela precisa responder a notificações push de APNs, definindo algumas visualizações de emblema. Mas como eu poderia obter o UIViewController
método in application:didReceiveRemoteNotification
: of AppDelegate.m
?
Eu tentei usar self.window.rootViewController
para obter a exibição atual UIViewController
, pode ser um UINavigationViewController
ou outro tipo de controlador de exibição. E eu descobri que a visibleViewController
propriedade de UINavigationViewController
pode ser usada para UIViewController
exibir a tela. Mas o que eu poderia fazer se não fosse um UINavigationViewController
?
Qualquer ajuda é apreciada! O código relacionado é o seguinte.
AppDelegate.m
...
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//I would like to find out which view controller is on the screen here.
UIViewController *vc = [(UINavigationViewController *)self.window.rootViewController visibleViewController];
[vc performSelector:@selector(handleThePushNotification:) withObject:userInfo];
}
...
ViewControllerA.m
- (void)handleThePushNotification:(NSDictionary *)userInfo{
//set some badge view here
}
fonte
UIView
instância. nãorootViewController
é necessariamente o controlador atualmente exibido. É apenas no topo da hierarquia de visualizações.Eu sempre adoro soluções que envolvem categorias, pois são fáceis de serem reutilizadas.
Então, eu criei uma categoria no UIWindow. Agora você pode chamar visibleViewController no UIWindow, e você obterá o controlador de exibição visível pesquisando a hierarquia do controlador. Isso funciona se você estiver usando o controle de navegação e / ou barra de guias. Se você tiver outro tipo de controlador para sugerir, entre em contato e posso adicioná-lo.
UIWindow + PazLabs.h (arquivo de cabeçalho)
UIWindow + PazLabs.m (arquivo de implementação)
Versão rápida
fonte
Extensão simples para UIApplication no Swift (preocupa-se ainda mais com o Controlador de Navegação
UITabBarController
no iPhone) :Uso simples:
Works perfect :-)
ATUALIZAÇÃO para código limpo:
fonte
Você também pode postar uma notificação via NSNotificationCenter. Isso permite que você lide com várias situações em que percorrer a hierarquia do controlador de exibição pode ser complicado - por exemplo, quando os modais estão sendo apresentados, etc.
Por exemplo,
Em cada um dos seus Controladores de exibição:
Você também pode usar essa abordagem para instrumentar controles que precisam ser atualizados quando uma notificação é recebida e são usados por vários controladores de exibição. Nesse caso, lide com as chamadas de observação de adição / remoção nos métodos init e dealloc, respectivamente.
fonte
addObserver:bar
dentroviewDidLoad
? Eu tenho que substituirself
?Código
Aqui está uma abordagem usando a excelente sintaxe de caso de switch no Swift 3/4/5 :
A idéia básica é a mesma da resposta do zirinisp, é apenas usar uma sintaxe mais semelhante ao Swift 3+.
Uso
Você provavelmente deseja criar um arquivo chamado
UIWindowExtension.swift
. Certifique-se de que inclui aimport UIKit
instrução, agora copie o código de extensão acima .No lado da chamada, ele pode ser usado sem nenhum controlador de exibição específico :
Ou, se você sabe que seu controlador de vista visível está acessível a partir de um controlador de vista específico :
Espero que ajude!
fonte
presentingViewController
e passarpresentingViewController.presentedViewController
como parâmetro para o método recursivo.UIWindow.visibleViewController(from: presentedViewController)
deveria serUIWindow.visibleViewController(from: presentingViewController.presentedViewController)
?presentedViewController
eviewController
é o mesmo objeto e ele chamará o método por si mesmo até a pilha estourar (trocadilho intencional). Assim serácase let presentingViewController where viewController?.presentedViewController != nil: return UIWindow.visibleViewController(from: presentingViewController.presentedViewController)
Eu descobri que o iOS 8 estragou tudo. No iOS 7, há um novo
UITransitionView
na hierarquia de visualizações sempre que você faz uma apresentação modalUINavigationController
. De qualquer forma, aqui está o meu código que encontra o mais alto VC. A chamadagetTopMostViewController
deve retornar um VC do qual você poderá enviar uma mensagem comopresentViewController:animated:completion
. Seu objetivo é obter um VC que você possa usar para apresentar um VC modal; portanto, ele provavelmente irá parar e retornar em classes de contêiner comoUINavigationController
e NÃO no VC contido nelas. Não deve ser difícil adaptar o código para fazer isso também. Testei esse código em várias situações no iOS 6, 7 e 8. Informe-me se encontrar bugs.fonte
Muito menos código do que todas as outras soluções:
Versão Objective-C:
Versão Swift 2.0: (crédito vai para Steve.B)
Funciona em qualquer lugar do seu aplicativo, mesmo com modais.
fonte
UINavigationController
que tem seus próprios filhos.Resposta de zirinisp em Swift:
Uso:
fonte
as!
enavigationController.visibleViewController!
para Swift 2.0Especifique o título para cada ViewController e obtenha o título do ViewController atual pelo código fornecido abaixo.
Em seguida, verifique pelo seu título como este
fonte
self.title = myPhotoView
O meu é melhor! :)
fonte
Por que não apenas manipular o código de notificação por push no delegado do aplicativo? Está diretamente relacionado a uma visualização?
Você pode verificar se a visualização de um UIViewController está visível no momento, verificando se a
window
propriedade da visualização possui um valor. Veja mais aqui .fonte
Apenas adição à resposta @zirinisp.
Crie um arquivo, nomeie-o
UIWindowExtension.swift
e cole o seguinte trecho:Use-o em qualquer lugar como:
Obrigado a @zirinisp.
fonte
Em relação à postagem do NSNotificationCenter acima (não é possível descobrir onde postar um comentário) ...
No caso de alguns estarem recebendo o tipo de erro - [NSConcreteNotification allKeys]. Mude isso:
para isso:
fonte
Isso funcionou para mim. Como tenho muitos alvos com controladores diferentes, as respostas anteriores não pareciam funcionar.
primeiro você quer isso dentro da sua classe AppDelegate:
então, na sua função
fonte
Esta é a melhor maneira possível que eu tentei. Se isso deve ajudar alguém ...
fonte
Com isso, você pode facilmente obter o controlador de exibição superior da postagem assim
Uma coisa a notar é que, se houver um UIAlertController atualmente sendo exibido,
UIApplication.topMostViewController
retornará aUIAlertController
.fonte
Versão Swift 2.0 da resposta de jungledev
fonte
Eu criei uma categoria para
UIApplication
comvisibleViewControllers
propriedade. A idéia principal é bem simples. I swizzledviewDidAppear
eviewDidDisappear
métodosUIViewController
. NoviewDidAppear
método, viewController é adicionado à pilha. NoviewDidDisappear
método, o viewController é removido da pilha.NSPointerArray
é usado em vez deNSArray
armazenarUIViewController
as referências de fraco . Essa abordagem funciona para qualquer hierarquia viewControllers.UIApplication + VisibleViewControllers.h
UIApplication + VisibleViewControllers.m
https://gist.github.com/medvedzzz/e6287b99011f2437ac0beb5a72a897f0
Versão Swift 3
UIApplication + VisibleViewControllers.swift
https://gist.github.com/medvedzzz/ee6f4071639d987793977dba04e11399
fonte
Sempre verifique sua configuração de compilação se estiver executando seu aplicativo com depuração ou versão.
NOTA IMPORTANTE: Não é possível testá-lo sem executar o aplicativo no modo de depuração
Esta foi a minha solução
fonte