Ich habe eine Ansicht auf den Navigationscontroller verschoben und wenn ich die Zurück-Taste drücke, wird automatisch zur vorherigen Ansicht gewechselt. Ich möchte ein paar Dinge tun, wenn die Zurück-Taste gedrückt wird, bevor die Ansicht vom Stapel genommen wird. Welches ist die Rückruffunktion der Zurück-Taste?
102
Antworten:
Die Antwort von William Jockusch löst dieses Problem mit einem einfachen Trick.
quelle
Meiner Meinung nach die beste Lösung.
Es funktioniert aber nur mit iOS5 +
quelle
Es ist wahrscheinlich besser, den Backbutton zu überschreiben, damit Sie das Ereignis behandeln können, bevor die Ansicht für Dinge wie die Benutzerbestätigung geöffnet wird.
Erstellen Sie in viewDidLoad ein UIBarButtonItem und setzen Sie self.navigationItem.leftBarButtonItem so, dass es in einem sel übergeben wird
Anschließend können Sie beispielsweise eine UIAlertView auslösen, um die Aktion zu bestätigen, und dann den Ansichts-Controller öffnen usw.
Anstatt einen neuen Backbutton zu erstellen, können Sie sich an die UINavigationController-Delegatmethoden anpassen, um Aktionen auszuführen, wenn der Back-Button gedrückt wird.
quelle
UINavigationControllerDelegate
hat keine Methoden, die aufgerufen werden, wenn die Zurück-Taste gedrückt wird.Dies ist der richtige Weg, um dies zu erkennen.
Diese Methode wird aufgerufen, wenn die Ansicht ebenfalls verschoben wird. Wenn Sie also parent == nil überprüfen, wird der View Controller vom Stapel entfernt
quelle
Am Ende habe ich diese Lösungen. Während wir auf die Schaltfläche "Zurück" tippen, wird die Methode viewDidDisappear aufgerufen. Wir können dies überprüfen, indem wir den isMovingFromParentViewController-Selektor aufrufen, der true zurückgibt. Wir können Daten zurückgeben (mit Delegate). Ich hoffe, dies hilft jemandem.
quelle
[super viewDidDisappear:animated]
Vielleicht ist es etwas zu spät, aber ich wollte das gleiche Verhalten auch schon früher. Und die Lösung, mit der ich mich entschieden habe, funktioniert in einer der Apps, die derzeit im App Store erhältlich sind, recht gut. Da ich noch niemanden gesehen habe, der mit einer ähnlichen Methode arbeitet, möchte ich sie hier teilen. Der Nachteil dieser Lösung ist, dass eine Unterklasse erforderlich ist
UINavigationController
. Obwohl die Verwendung von Method Swizzling helfen könnte, dies zu vermeiden, bin ich nicht so weit gegangen.Die Standard-Zurück-Schaltfläche wird also tatsächlich von verwaltet
UINavigationBar
. Wenn ein Benutzer auf die Schaltfläche "Zurück" tippt,UINavigationBar
fragen Sie seinen Delegierten, ob erUINavigationItem
bei einem Anruf die Spitze öffnen sollnavigationBar(_:shouldPop:)
.UINavigationController
implementieren Sie dies tatsächlich, aber es erklärt nicht öffentlich, dass es annimmtUINavigationBarDelegate
(warum!?). Um dieses Ereignis abzufangen, erstellen Sie eine Unterklasse vonUINavigationController
, deklarieren Sie deren Konformität mitUINavigationBarDelegate
und implementieren Sie sienavigationBar(_:shouldPop:)
. Geben Sie zurück,true
wenn der oberste Gegenstand geknallt werden soll. Rückkehrfalse
wenn es bleiben soll.Es gibt zwei Probleme. Das erste ist, dass Sie die
UINavigationController
Version vonnavigationBar(_:shouldPop:)
irgendwann aufrufen müssen . Erklärt esUINavigationBarController
aber nicht öffentlich als konformUINavigationBarDelegate
, führt der Versuch, es aufzurufen, zu einem Fehler bei der Kompilierung. Die Lösung, die ich gewählt habe, besteht darin, die Objective-C-Laufzeit zu verwenden, um die Implementierung direkt abzurufen und aufzurufen. Bitte lassen Sie mich wissen, wenn jemand eine bessere Lösung hat.Das andere Problem ist, dass
navigationBar(_:shouldPop:)
zuerst aufgerufen wird,popViewController(animated:)
wenn der Benutzer auf die Zurück-Schaltfläche tippt. Die Reihenfolge wird umgekehrt, wenn der View Controller durch Aufrufen geöffnet wirdpopViewController(animated:)
. In diesem Fall verwende ich einen Booleschen Wert, um festzustellen, obpopViewController(animated:)
zuvor aufgerufen wurde,navigationBar(_:shouldPop:)
was bedeutet, dass der Benutzer auf die Schaltfläche "Zurück" getippt hat.Außerdem mache ich eine Erweiterung von
UIViewController
, damit der Navigations-Controller den Ansichts-Controller fragt, ob er geöffnet werden soll, wenn der Benutzer auf die Zurück-Schaltfläche tippt. View Controller können zurückkehrenfalse
und alle erforderlichen Aktionen ausführen undpopViewController(animated:)
später aufrufen .Und in Ihren View-Controllern implementieren
shouldBePopped(_:)
. Wenn Sie diese Methode nicht implementieren, wird standardmäßig der Ansichts-Controller geöffnet, sobald der Benutzer wie gewohnt auf die Schaltfläche "Zurück" tippt.Sie können meine Demo hier ansehen .
quelle
Für "BEVOR Sie die Ansicht vom Stapel nehmen":
quelle
Es gibt einen angemesseneren Weg, als die viewController zu fragen. Sie können Ihren Controller zu einem Delegaten der Navigationsleiste machen, die über die Schaltfläche "Zurück" verfügt. Hier ist ein Beispiel. Geben Sie in der Implementierung des Controllers, in dem Sie das Drücken der Zurück-Taste ausführen möchten, an, dass das UINavigationBarDelegate-Protokoll implementiert wird:
Machen Sie Ihren Controller dann irgendwo in Ihrem Initialisierungscode (wahrscheinlich in viewDidLoad) zum Delegaten seiner Navigationsleiste:
Implementieren Sie abschließend die Methode shouldPopItem. Diese Methode wird sofort aufgerufen, wenn die Zurück-Taste gedrückt wird. Wenn Sie mehrere Controller oder Navigationselemente im Stapel haben, möchten Sie wahrscheinlich überprüfen, welches dieser Navigationselemente angezeigt wird (der Elementparameter), damit Sie Ihre benutzerdefinierten Aufgaben nur dann ausführen, wenn Sie dies erwarten. Hier ist ein Beispiel:
quelle
Wenn Sie "viewWillDisappear" oder eine ähnliche Methode nicht verwenden können, versuchen Sie, UINavigationController in eine Unterklasse zu unterteilen. Dies ist die Header-Klasse:
Implementierungsklasse:
Auf der anderen Seite müssen Sie diesen viewController mit Ihrem benutzerdefinierten NavigationController verknüpfen. Führen Sie in Ihrer viewDidLoad-Methode für Ihren regulären viewController Folgendes aus:
quelle
Hier ist eine andere Möglichkeit, die ich implementiert habe (habe sie nicht mit einem Abwicklungsabschnitt getestet, aber wahrscheinlich nicht differenziert, wie andere in Bezug auf andere Lösungen auf dieser Seite angegeben haben), damit der übergeordnete Ansichts-Controller Aktionen ausführt, bevor die untergeordnete VC, die er gepusht hat wird vom Ansichtsstapel entfernt (ich habe dies ein paar Ebenen tiefer als der ursprüngliche UINavigationController verwendet). Dies kann auch verwendet werden, um Aktionen auszuführen, bevor die childVC ebenfalls gepusht wird. Dies hat den zusätzlichen Vorteil, dass Sie mit der Zurück-Schaltfläche des iOS-Systems arbeiten können, anstatt ein benutzerdefiniertes UIBarButtonItem oder UIButton erstellen zu müssen.
Lassen Sie Ihren übergeordneten VC das
UINavigationControllerDelegate
Protokoll übernehmen und sich für delegierte Nachrichten registrieren:Implementieren Sie diese
UINavigationControllerDelegate
Instanzmethode inMyParentViewController
:Wenn Sie in der obigen
UINavigationControllerDelegate
Instanzmethode eine bestimmte Rückruffunktion angeben}}
quelle
Das funktioniert bei mir in Swift:
quelle
Wenn Sie ein Storyboard verwenden und aus einem Push-Segment kommen, können Sie es auch einfach überschreiben
shouldPerformSegueWithIdentifier:sender:
.quelle