Wie finden Sie das oberste view-controller auf iOS
Ich habe in ein paar Fällen nun, wo es wäre praktisch in der Lage sein zu finden, das "topmost" - view-controller (der verantwortliche für die aktuelle Sicht), aber noch keinen Weg gefunden, es zu tun.
Grundsätzlich die Herausforderung ist diese: Angesichts der Tatsache, dass man die Ausführung in einer Klasse, die nicht eine view-controller (oder einen Blick) [und nicht die Adresse eines active view] und wurde nicht übergeben Sie die Adresse der oberste view-controller (oder, sagen wir, die Adresse des navigation-controller), ist es möglich zu finden, die view-controller? (Und, wenn ja, wie?)
Oder, wenn das fehlschlägt, ist es möglich, die oberste Ansicht?
- Sie sagen also, es ist nicht möglich.
- Nein, sage ich, dass es scheint, wie dein code könnte etwas re-Design, denn Sie sollten nur selten brauchen, um wissen. Auch die Idee der "oberste" ist nur gültig in bestimmten Kontexten, und selbst dann nicht immer.
- Ich hatte deine Frage falsch verstanden. Es gibt viele wenn und aber versucht, diese Frage zu beantworten. Es hängt von Ihrem view-controller fließen. @Wilbur ' s Antwort sollte ein guter Ausgangspunkt, um die Spur nach unten.
- Gut, wir vereinfachen es zu einem konkreten Fall. Wenn ich schreiben wollte, ein Klon der uialertview-Objekt, wie würde ich es tun? Beachten Sie, dass es funktionieren kann gut ohne übergeben alle addressibility zu anderen Controllern oder views.
- Hinzufügen eines zweiten UIWindow funktioniert gut für die Alarm-Ansicht-wie überlagerungen.
- Ja, UIWindow scheint der Weg für eine Warnung. Nicht lösen das andere problem, herauszufinden, die oberste view-controller (wo man will, stellen Sie noch on top), aber ich denke, diese müssen getrennt behandelt werden.
- Was, wenn Sie wirklich brauchen, in einigen besonderen Fall mehr als ein uialertview-Objekt in ein Modul, wo man nur die Daten verarbeiten? Sie wollen nicht Durcheinander herum mit einem controller Referenz im Daten-Modul, kümmert sich um es richtig in allen UI, wo Sie nennen das Daten-Modul. Oder Sie tun? Und vielleicht besser ist, um eine in-zwischen Schicht... ich bin gerade am überlegen hier... Sie könnten Recht haben wenn.
Du musst angemeldet sein, um einen Kommentar abzugeben.
iOS 4 eingeführt, die property rootViewController auf UIWindow:
Müssen Sie ihn selbst festlegen nach dem erstellen der view-controller, obwohl.
-[UINavigationController topViewController]
). Dann gibt es Wort „Wurzel“, die die Wurzel des Baums (wie-[UIWindow rootViewController]
.UIViewController
und nichtUIWindow
.Ich glaube, Sie brauchen eine Kombination von die akzeptierte Antwort, und @fishstix ist
Swift 3.0+
UINavigationController
und Fragen, für seinetopViewController
oder auch check fürUITabBarController
und bitten Sie umselectedViewController
. Diese erhalten Sie den view-controller, der aktuell für den Benutzer sichtbar.s
keyWindow.rootViewController " ist immer_UIModalItemsPresentingViewController
bei mir (iOS 7). Allerdings, wenn ich dieappDelegate.window
Eigenschaft, es gibt den controller, den ich wollte.presentingViewController
, weil einige view-Controller können ` definesPresentationContext` JAAbgeschlossen JonasG ist Antwort (die Links aus tab bar Controller beim überqueren), hier ist meine version von der Rückkehr der aktuell sichtbare view-controller:
childViewControllers
Eine komplette nicht-rekursive version, kümmert sich um verschiedene Szenarien:
UINavigationController
UITabBarController
Objective-C
Swift 4+
visibleViewController
deutlich zu machen, was es tut.Immer top-die meisten view-controller für Swift mit Erweiterungen
Code:
Verwendung:
Abgeschlossen Erics Antwort (die Links aus popovers, navigation-Controller, tabbarcontrollers, view-Controller Hinzugefügt, wie Untersichten, um einige der anderen view-Controller beim überqueren), hier ist meine version von der Rückkehr der aktuell sichtbare view-controller:
=====================================================================
=====================================================================
Und alles was Sie jetzt tun müssen, um zu bekommen, meisten top-view-controller ist, rufen Sie die oben beschriebene Methode wie folgt:
Diese Antwort enthält
childViewControllers
und unterhält eine saubere und lesbare Umsetzung.Vor kurzem habe ich diese situation in mein Projekt, die erforderlich ist, um angezeigt, eine Benachrichtigung anzeigen, was der controller angezeigt wurde, und das, was war der Typ (UINavigationController, classic controller oder custom-view-controller), wenn Netzwerk-status geändert.
So, ich juste veröffentlicht mein code, die ist ganz einfach und basiert auf einem Protokoll, so dass es flexibel ist, mit jeder Art von container-controller.
Es scheint verwandt zu sein mit den letzten Antworten, aber in einer sehr flexiblen Art und Weise.
Du kannst dir den code hier ein : PPTopMostController
Und bekam die meisten top-controller mit
Dies ist eine Verbesserung um Eric ' s Antwort:
_topMostController(UIViewController *cont)
ist eine Hilfsfunktion.Alles was Sie jetzt tun müssen, ist Anruf
topMostController()
und die meisten top-UIViewController zurückgegeben werden soll!self
gehören sollte.Einfache Erweiterung für
UIApplication
Swift:HINWEIS:
Es kümmert sich um
moreNavigationController
innerhalbUITabBarController
Einfache Nutzung:
Hier ist mein nehmen auf diese. Dank @Stakenborg für den Hinweis auf die Art und Weise überspringen erste uialertview-Objekt, wie die meisten top-controller
getSomething:
in Objective-C. Dies hat eine Besondere Bedeutung (mehr: cocoadevcentral.com/articles/000082.php) und Sie nicht erfüllen diese Anforderungen in code.Für die neuesten Swift-Version:
Erstellen Sie eine Datei, nennen Sie es
UIWindowExtension.swift
und fügen Sie den folgenden Codeausschnitt:Verwenden Sie es überall:
switch
statt if-else. 3. nicht sicher, Sie brauchen eine statische Funktion als gut, ich denke, man könnte dies leicht in der ersten Instanz-Ebene var deklariert. 4. Wahrscheinlich am besten nicht zu schaffen, zu viele Globale Funktionen, aber das ist Geschmackssache. Sie können eine Zeile code zu erreichen, die Globale Funktion, Wirkung:UIApplication.sharedApplication().delegate?.window?.visibleViewController
Hier ist was für mich gearbeitet.
Fand ich, dass manchmal der controller war gleich null auf die wichtigsten Fenster, wie die keyWindow einige OS, was wie eine Warnung, etc.
Erweiterung auf @Eric ' s Antwort, die Sie müssen vorsichtig sein, dass die keyWindow ist eigentlich das Fenster, das Sie wollen. Wenn Sie versuchen, verwenden Sie diese Methode nach dem Tippen etwas in eine Warnung anzeigen, zum Beispiel, die keyWindow tatsächlich werden dem alert-Fenster, und das wird zu Problemen führen, für Sie keine Zweifel. Dies geschah zu mir in den wilden bei der Handhabung von deep-links über eine Warnmeldung und verursacht SIGABRTs KEINE STACK-TRACE. Insgesamt Hündin zu Debuggen.
Hier ist der code, den ich jetzt verwende:
Fühlen Sie sich frei zu mischen, diese mit was auch immer Geschmack von abrufen der top-view-controller, die Sie aus den anderen Antworten auf diese Frage.
Alternative Swift-Lösung:
Weiteres Swift-Lösung
Dieser Lösung ist die komplette. Es dauert in Berücksichtigung:
UINavigationController
UIPageViewController
UITabBarController
Und die oberste vorgestellt view-controller aus der top-view-controller
Beispiel ist in Swift 3.
Gibt es 3 überladungen
Swift 4.2 Erweiterung
Verwenden Sie es von überall wie,
oder wie,
Passt auf alle Klassen, wie UINavigationController, UITabBarController
Genießen!
Große Lösung in Swift, implementieren Sie in AppDelegate
Ich denke, die meisten Antworten völlig ignoriert haben
UINavigationViewController
, so habe ich mich entschlossen diesen Anwendungsfall mit folgenden Umsetzung.Nicht sicher, ob dies wird Ihnen helfen, was Sie versuchen zu erreichen, indem die oberste view-controller, aber ich habe versucht eine neue view-controller, aber wenn mein root-view-controller hatte bereits einen modalen dialog blockiert werden würde, so würde ich Zyklus an die Spitze aller modal-view-Controller, mit diesem code:
Swift:
Verwendung:
Unter zwei-Funktion kann helfen, zu finden, die topViewController auf Stapel von view-Controller. Möglicherweise müssen Sie die Anpassung später, aber für diesen code ist genial zu verstehen, das Konzept der topViewController oder einem Stapel von viewControllers.
Können Sie mit [viewController-Klasse] Methode, um herauszufinden, die Art der Klasse von einem viewController.
Und anderen Swift-Lösung
Viele dieser Antworten sind unvollständig. Obwohl dies in Objective-C, dies ist die beste Zusammenstellung aller von Ihnen, dass konnte ich zusammen für jetzt, wie eine nicht-rekursive block:
Link zu Gist, in Fall wird es überarbeitet: https://gist.github.com/benguild/0d149bb3caaabea2dac3d2dca58c0816
Code für Referenz/Vergleich:
Verwenden Sie die folgende Erweiterung zu greifen, aktuell sichtbare
UIViewController
. Arbeitete für Swift 4.0 und höherCode:
Wie zu benutzen?
Wenn das root-controller, einen navigation-controller, richtigen Weg zu finden oben sichtbar controller:
Hier ein Auszug aus UINavigationController.h:
Dies funktioniert für die Suche nach top-viewController Eins von Wurzel-view controlle
den Sie finden konnten, die meisten top-view-controller mithilfe
self
hat keinenavigationController
Eigenschaft.Andere Lösung stützt sich auf die responder-Kette, die möglicherweise oder möglicherweise nicht arbeiten, je nachdem, was der first responder ist:
Beispiel pseudo-code:
Zu vermeiden, eine Menge von Komplexität verfolgen Sie die aktuellen viewController durch die Schaffung eines viewController im delegieren und setzen Sie es selbst in jedem viewDidLoad-Methode, auf diese Weise jederzeit laden Sie eine neue Sicht der ViewController in der statt zu delegieren, entsprechen diese Ansicht ist viewController. Dies kann hässlich sein, aber es funktioniert wunderbar, und es gibt keine Notwendigkeit, ein navigation-controller oder irgendwelchen Unsinn.
Vorherige Antwort scheint nicht, um Fälle zu behandeln, wo rootController sind UITabBarController oder UINavigationController.
Hier ist die Funktion in swift, die Werke für solche Fälle :
Ich denke, die Lösung von Rajesh ist fast perfekt, aber ich denke, es ist besser traverse Untersichten von oben nach unten, ich folgt geändert:
Hier ist eine Rasche Umsetzung einer app mit UINavigationController ist, als eine Wurzel.
Ich denke, dass vielleicht eine Sache, die übersehen hier. Vielleicht ist es besser zu übergeben die Eltern viewController in der Funktion, die mit dem viewController. Wenn Sie Angeln um in der view-Hierarchie finden Sie die top-view-controller, dass es wahrscheinlich gegen die Trennung der Modell-Ebene-und UI-Schicht und ist ein code smell. Nur den Hinweis, ich Tat das gleiche, dann erkannte, es war viel einfacher, nur zu passieren in Funktion, indem er das Modell ckkehr auf die UI-Ebene, wo ich eine Referenz auf den view-controller.
Eine knappe, aber umfassende Lösung im Swift-4.2, berücksichtigt UINavigationControllers, UITabBarControllers, vorgestellt und Kind view-Controller:
Verwendung:
Mein Problem ein bisschen anders war, ich eine mit SWRevealViewController in meiner Anwendung.
Ich verwendet Yuchen Zhong ist Antwort aber es immer wieder topViewController als SWRevealViewController. Für diejenigen, die mit SWRevealViewController oder einen anderen pod zu entwickeln, oberen Bereich. Hier ist meine Erweiterung von Yuchen Zhong Antwort:
Sollten Sie verwenden:
Wenn es eine uiactionsheet auf
[UIApplication sharedApplication].keyWindow
ist es nicht Recht zu verwenden keyWindow wie bereits in diese Antwort.