Der aktuelle UIViewController
Bildschirm muss auf Push-Benachrichtigungen von APNs reagieren, indem einige Ausweisansichten festgelegt werden. Aber wie könnte ich die UIViewController
In-Methode bekommen application:didReceiveRemoteNotification
: von AppDelegate.m
?
Ich habe versucht self.window.rootViewController
, die aktuelle Anzeige zu erhalten UIViewController
, es kann sich um eine UINavigationViewController
oder eine andere Art von Ansichtssteuerung handeln. Und ich finde heraus, dass die visibleViewController
Eigenschaft von UINavigationViewController
verwendet werden kann, um das UIViewController
auf den Bildschirm zu bekommen . Aber was könnte ich tun, wenn es kein ist UINavigationViewController
?
Jede Hilfe wird geschätzt! Der zugehörige Code lautet wie folgt.
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
}
quelle
UIView
Instanz zum Controller zu gelangen .rootViewController
ist nicht unbedingt der aktuell gezeigte Controller. Es befindet sich ganz oben in der Ansichtshierarchie.Ich liebe immer Lösungen, die Kategorien beinhalten, da sie fest miteinander verbunden sind und leicht wiederverwendet werden können.
Also habe ich eine Kategorie auf UIWindow erstellt. Sie können jetzt visibleViewController unter UIWindow aufrufen. Dadurch erhalten Sie den Controller für sichtbare Ansichten, indem Sie die Controller-Hierarchie durchsuchen. Dies funktioniert, wenn Sie einen Navigations- und / oder Registerkarten-Controller verwenden. Wenn Sie einen anderen Controllertyp vorschlagen möchten, lassen Sie es mich bitte wissen und ich kann ihn hinzufügen.
UIWindow + PazLabs.h (Header-Datei)
UIWindow + PazLabs.m (Implementierungsdatei)
Schnelle Version
quelle
Einfache Erweiterung für UIApplication in Swift (kümmert sich sogar um moreNavigationController
UITabBarController
auf dem iPhone) :Einfache Verwendung:
Funktioniert perfekt :-)
UPDATE für sauberen Code:
quelle
Sie können auch eine Benachrichtigung über NSNotificationCenter veröffentlichen. Auf diese Weise können Sie eine Reihe von Situationen bewältigen, in denen das Durchlaufen der View-Controller-Hierarchie schwierig sein kann - beispielsweise wenn Modalitäten usw. präsentiert werden.
Z.B,
In jedem Ihrer View Controller:
Sie können diesen Ansatz auch für Instrumentensteuerungen verwenden, die beim Empfang einer Benachrichtigung aktualisiert werden müssen und von mehreren Ansichtssteuerungen verwendet werden. Behandeln Sie in diesem Fall die Aufrufe zum Hinzufügen / Entfernen von Beobachtern in den Methoden init bzw. dealloc.
quelle
addObserver:bar
drinviewDidLoad
? Muss ich durch ersetzenself
?Code
Hier ist ein Ansatz, der die großartige Switch-Case-Syntax in Swift 3/4/5 verwendet :
Die Grundidee ist die gleiche wie in der Antwort von zirinisp, es wird nur eine schnellere 3+ Syntax verwendet.
Verwendung
Sie möchten wahrscheinlich eine Datei mit dem Namen erstellen
UIWindowExtension.swift
. Stellen Sie sicher, dass dieimport UIKit
Anweisung enthalten ist, und kopieren Sie nun den obigen Erweiterungscode .Auf der Anrufseite kann es entweder ohne einen bestimmten View Controller verwendet werden :
Oder wenn Sie wissen, dass Ihr sichtbarer Ansichts-Controller von einem bestimmten Ansichts-Controller aus erreichbar ist :
Ich hoffe, es hilft!
quelle
presentingViewController
undpresentingViewController.presentedViewController
als Parameter an die rekursive Methode zu übergeben.UIWindow.visibleViewController(from: presentedViewController)
sollte stattdessen seinUIWindow.visibleViewController(from: presentingViewController.presentedViewController)
?presentedViewController
undviewController
ist das gleiche Objekt und es wird die Methode mit sich selbst aufrufen, bis der Stapel überläuft (Wortspiel beabsichtigt). So wird es seincase let presentingViewController where viewController?.presentedViewController != nil: return UIWindow.visibleViewController(from: presentingViewController.presentedViewController)
Ich habe festgestellt, dass iOS 8 alles vermasselt hat. In iOS 7 gibt es eine neue
UITransitionView
Ansichtshierarchie, wenn Sie eine modale Darstellung habenUINavigationController
. Wie auch immer, hier ist mein Code, der die oberste VC erhält. Das AnrufengetTopMostViewController
sollte eine VC zurückgeben, die Sie wie folgt senden können solltenpresentViewController:animated:completion
. Der Zweck ist es, Ihnen eine VC zu besorgen, mit der Sie eine modale VC präsentieren können, damit sie höchstwahrscheinlich bei Containerklassen wieUINavigationController
und NICHT bei der darin enthaltenen VC anhält und zurückkehrt . Sollte nicht schwer sein, den Code auch dafür anzupassen. Ich habe diesen Code in verschiedenen Situationen in iOS 6, 7 und 8 getestet. Bitte lassen Sie mich wissen, wenn Sie Fehler finden.quelle
Weit weniger Code als alle anderen Lösungen:
Objective-C-Version:
Swift 2.0-Version: (Gutschrift geht an Steve.B)
Funktioniert überall in Ihrer App, auch mit Modalen.
quelle
UINavigationController
eigenen untergeordneten Controller hat.zirinisps Antwort in Swift:
Verwendung:
quelle
as!
undnavigationController.visibleViewController!
für Swift 2.0Geben Sie den Titel für jeden ViewController an und erhalten Sie den Titel des aktuellen ViewControllers mit dem unten angegebenen Code.
Dann überprüfen Sie es anhand Ihres Titels wie folgt
quelle
self.title = myPhotoView
Meins ist besser! :) :)
quelle
Warum nicht einfach den Push-Benachrichtigungscode im App-Delegaten verarbeiten? Steht es in direktem Zusammenhang mit einer Ansicht?
Sie können überprüfen, ob die Ansicht eines UIViewControllers derzeit sichtbar ist, indem Sie überprüfen, ob die
window
Eigenschaft der Ansicht einen Wert hat. Sehen Sie hier mehr .quelle
Nur Ergänzung zu @zirinisp Antwort.
Erstellen Sie eine Datei, benennen Sie sie
UIWindowExtension.swift
und fügen Sie das folgende Snippet ein:Verwenden Sie es überall als:
Danke an @zirinisp.
quelle
In Bezug auf NSNotificationCenter Post oben (leider kann ich nicht herausfinden, wo ich einen Kommentar darunter posten kann ...)
Für den Fall, dass einige den Fehler - [NSConcreteNotification allKeys] erhalten haben. Ändere das:
dazu:
quelle
Das hat bei mir funktioniert. Ich habe viele Ziele mit unterschiedlichen Controllern, sodass frühere Antworten nicht zu funktionieren schienen.
Zuerst möchten Sie dies in Ihrer AppDelegate-Klasse:
dann in Ihrer Funktion
quelle
Dies ist der bestmögliche Weg, den ich ausprobiert habe. Wenn es jemandem helfen sollte ...
quelle
Mit diesem können Sie ganz einfach den Top-Post-View-Controller so bekommen
Zu beachten ist, dass, wenn derzeit ein UIAlertController angezeigt wird, a zurückgegeben
UIApplication.topMostViewController
wirdUIAlertController
.quelle
Schnelle 2.0-Version von Jungledevs Antwort
quelle
Ich habe eine Kategorie für
UIApplication
mitvisibleViewControllers
Eigenschaft erstellt. Die Hauptidee ist ziemlich einfach. Ich zischteviewDidAppear
undviewDidDisappear
Methoden inUIViewController
. In derviewDidAppear
Methode viewController wird dem Stapel hinzugefügt. In derviewDidDisappear
Methode viewController wird vom Stapel entfernt.NSPointerArray
wird verwendet, anstattNSArray
schwach zu speichernUIViewController
Referenzen . Dieser Ansatz funktioniert für jede viewController-Hierarchie.UIApplication + VisibleViewControllers.h
UIApplication + VisibleViewControllers.m
https://gist.github.com/medvedzzz/e6287b99011f2437ac0beb5a72a897f0
Swift 3 Version
UIApplication + VisibleViewControllers.swift
https://gist.github.com/medvedzzz/ee6f4071639d987793977dba04e11399
quelle
Überprüfen Sie immer Ihre Build-Konfiguration, wenn Sie Ihre App mit Debug oder Release ausführen.
WICHTIGER HINWEIS: Sie können es nicht testen, ohne Ihre App im Debug-Modus auszuführen
Das war meine Lösung
quelle