Le courant UIViewController
à l'écran doit répondre aux notifications push des APN, en définissant certaines vues de badge. Mais comment pourrais-je obtenir la UIViewController
méthode in application:didReceiveRemoteNotification
: of AppDelegate.m
?
J'ai essayé d'utiliser self.window.rootViewController
pour obtenir l'affichage actuel UIViewController
, cela peut être un UINavigationViewController
ou un autre type de contrôleur de vue. Et je découvre que la visibleViewController
propriété de UINavigationViewController
peut être utilisée pour obtenir le UIViewController
sur l'écran. Mais que pourrais-je faire si ce n'est pas unUINavigationViewController
?
Toute aide est appréciée! Le code associé est le suivant.
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
}
UIView
instance.rootViewController
n'est pas nécessairement le contrôleur actuellement affiché. C'est juste en haut de la hiérarchie des vues.J'aime toujours les solutions qui impliquent des catégories car elles sont boulonnées et peuvent être facilement réutilisées.
J'ai donc créé une catégorie sur UIWindow. Vous pouvez maintenant appeler visibleViewController sur UIWindow et cela vous donnera le contrôleur de vue visible en recherchant dans la hiérarchie du contrôleur. Cela fonctionne si vous utilisez la navigation et / ou le contrôleur de barre d'onglets. Si vous avez un autre type de contrôleur à suggérer, faites-le moi savoir et je pourrai l'ajouter.
UIWindow + PazLabs.h (fichier d'en-tête)
UIWindow + PazLabs.m (fichier d'implémentation)
Version Swift
la source
Extension simple pour UIApplication dans Swift (se soucie même de plus deNavigationController
UITabBarController
sur iPhone) :Utilisation simple:
Fonctionne parfaitement :-)
MISE À JOUR pour le code propre:
la source
Vous pouvez également publier une notification via NSNotificationCenter. Cela vous permet de gérer un certain nombre de situations dans lesquelles la traversée de la hiérarchie du contrôleur de vue peut être délicate - par exemple lorsque des modaux sont présentés, etc.
Par exemple,
Dans chacun de vos contrôleurs d'affichage:
Vous pouvez également utiliser cette approche pour les commandes d'instruments qui doivent être mises à jour lorsqu'une notification est reçue et sont utilisées par plusieurs contrôleurs de vue. Dans ce cas, gérez les appels d'observateur d'ajout / suppression dans les méthodes init et dealloc, respectivement.
la source
addObserver:bar
intérieurviewDidLoad
? Dois-je remplacer parself
?Code
Voici une approche utilisant la grande syntaxe de cas de commutation dans Swift 3/4/5 :
L'idée de base est la même que dans la réponse de zirinisp, il utilise simplement une syntaxe plus Swift 3+.
Usage
Vous souhaitez probablement créer un fichier nommé
UIWindowExtension.swift
. Assurez-vous qu'il inclut l'import UIKit
instruction, copiez maintenant le code d'extension ci-dessus .Du côté appel, il peut être utilisé sans contrôleur de vue spécifique :
Ou si vous savez que votre contrôleur de vue visible est accessible à partir d'un contrôleur de vue spécifique :
J'espère que ça aide!
la source
presentingViewController
et à le passerpresentingViewController.presentedViewController
comme paramètre à la méthode récursive.UIWindow.visibleViewController(from: presentedViewController)
devrait plutôt l'êtreUIWindow.visibleViewController(from: presentingViewController.presentedViewController)
?presentedViewController
etviewController
c'est le même objet et il appellera la méthode avec lui-même jusqu'à ce que la pile déborde (jeu de mots prévu). Alors ça va êtrecase let presentingViewController where viewController?.presentedViewController != nil: return UIWindow.visibleViewController(from: presentingViewController.presentedViewController)
J'ai constaté qu'iOS 8 a tout gâché. Dans iOS 7, il y a un nouveau
UITransitionView
sur la hiérarchie des vues chaque fois que vous avez une présentation modaleUINavigationController
. Quoi qu'il en soit, voici mon code qui trouve obtient le VC le plus élevé. L'appelgetTopMostViewController
devrait renvoyer un VC auquel vous devriez pouvoir envoyer un message commepresentViewController:animated:completion
. Son but est de vous obtenir un VC que vous pouvez utiliser pour présenter un VC modal, donc il s'arrêtera probablement et retournera aux classes de conteneurs commeUINavigationController
et NON au VC qu'ils contiennent. Il ne devrait pas être difficile d'adapter le code pour le faire aussi. J'ai testé ce code dans diverses situations sous iOS 6, 7 et 8. Veuillez me faire savoir si vous trouvez des bogues.la source
Beaucoup moins de code que toutes les autres solutions:
Version Objective-C:
Version Swift 2.0: (le mérite revient à Steve.B)
Fonctionne n'importe où dans votre application, même avec des modaux.
la source
UINavigationController
qui a ses propres enfants.Réponse de zirinisp dans Swift:
Usage:
la source
as!
etnavigationController.visibleViewController!
pour Swift 2.0Spécifiez le titre de chaque ViewController, puis obtenez le titre du ViewController actuel à l'aide du code ci-dessous.
Ensuite, vérifiez-le par votre titre comme ceci
la source
self.title = myPhotoView
Le mien est meilleur! :)
la source
Pourquoi ne pas simplement gérer le code de notification push dans le délégué d'application? Est-ce directement lié à une vue?
Vous pouvez vérifier si la vue d'un UIViewController est actuellement visible en vérifiant si sa
window
propriété de vue a une valeur. En savoir plus ici .la source
Juste un ajout à la réponse @zirinisp.
Créez un fichier, nommez-le
UIWindowExtension.swift
et collez l'extrait suivant:Utilisez-le n'importe où comme:
Merci à @zirinisp.
la source
Concernant NSNotificationCenter Post ci-dessus (désolé, je ne peux pas savoir où publier un commentaire en dessous ...)
Au cas où certains obtiendraient l'erreur - [NSConcreteNotification allKeys] de toutes sortes. Change ça:
pour ça:
la source
Cela a fonctionné pour moi. J'ai de nombreuses cibles qui ont des contrôleurs différents, donc les réponses précédentes ne semblaient pas fonctionner.
vous voulez d'abord ceci dans votre classe AppDelegate:
puis, dans ta fonction
la source
C'est la meilleure façon possible que j'ai essayée. Si cela devait aider quelqu'un ...
la source
Avec cela, vous pouvez facilement obtenir le contrôleur de vue post supérieur comme ceci
Une chose à noter est que si un UIAlertController est actuellement affiché,
UIApplication.topMostViewController
retournera un fichierUIAlertController
.la source
Version Swift 2.0 de la réponse de Jungledev
la source
J'ai créé une catégorie pour
UIApplication
avecvisibleViewControllers
propriété. L'idée principale est assez simple. J'ai swizzedviewDidAppear
et lesviewDidDisappear
méthodes dedansUIViewController
. Dans laviewDidAppear
méthode, viewController est ajouté à la pile. Dans laviewDidDisappear
méthode, viewController est supprimé de la pile.NSPointerArray
est utilisé au lieu deNSArray
pour stocker faibleUIViewController
les références . Cette approche fonctionne pour n'importe quelle hiérarchie viewControllers.UIApplication + VisibleViewControllers.h
UIApplication + VisibleViewControllers.m
https://gist.github.com/medvedzzz/e6287b99011f2437ac0beb5a72a897f0
Version Swift 3
UIApplication + VisibleViewControllers.swift
https://gist.github.com/medvedzzz/ee6f4071639d987793977dba04e11399
la source
Vérifiez toujours la configuration de votre build si vous exécutez votre application avec le débogage ou la version.
REMARQUE IMPORTANTE: vous ne pouvez pas le tester sans exécuter votre application en mode débogage
C'était ma solution
la source