Ich versuche, die Standardaktion der Zurück-Schaltfläche in einem Navigationscontroller zu überschreiben. Ich habe einem Ziel eine Aktion auf der benutzerdefinierten Schaltfläche bereitgestellt. Das Seltsame ist, wenn es zugewiesen wird, obwohl das Backbutton-Attribut es ihnen nicht beachtet und es nur die aktuelle Ansicht öffnet und zum Stamm zurückkehrt:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle: @"Servers"
style:UIBarButtonItemStylePlain
target:self
action:@selector(home)];
self.navigationItem.backBarButtonItem = backButton;
Sobald ich es durch das leftBarButtonItem
auf eingestellt navigationItem
habe, ruft es meine Aktion auf, aber dann sieht der Knopf wie ein einfacher runder aus, anstatt wie der mit einem Pfeil nach hinten:
self.navigationItem.leftBarButtonItem = backButton;
Wie kann ich meine benutzerdefinierte Aktion aufrufen, bevor ich zur Stammansicht zurückkehre? Gibt es eine Möglichkeit, die Standard-Back-Aktion zu überschreiben, oder gibt es eine Methode, die beim Verlassen einer Ansicht immer aufgerufen wird ( viewDidUnload
funktioniert das nicht)?
Antworten:
Versuchen Sie, dies in den Ansichts-Controller zu legen, in dem Sie die Presse erkennen möchten:
quelle
if (find(self.navigationController!.viewControllers as! [UIViewController],self)==nil)
Ich habe die Erweiterung UIViewController-BackButtonHandler implementiert . Es muss nichts unterklassifiziert werden. Fügen Sie es einfach in Ihr Projekt ein und überschreiben Sie die
navigationShouldPopOnBackButton
Methode in derUIViewController
Klasse:Beispiel-App herunterladen .
quelle
navigationBar:shouldPopItem:
ist keine private Methode, da es Teil desUINavigationBarDelegate
Protokolls ist.YES
)? oder wird es in Zukunft? Unterklassen sind wahrscheinlich eine sicherere OptionNO
die Zurück-Schaltfläche nach dem Zurückkehren deaktiviert bleibt (visuell, da sie weiterhin Berührungsereignisse empfängt und darauf reagiert). Ich habe es umgangen, indem ichelse
dershouldPop
Prüfung eine Anweisung hinzugefügt und die Unteransichten der Navigationsleiste durchlaufen habe und denalpha
Wert in einem Animationsblock bei Bedarf auf 1 zurückgesetzt habe: gist.github.com/idevsoftware/9754057Anders als Amagrammer sagte, ist es möglich. Sie müssen Ihre Unterklasse
navigationController
. Ich habe hier alles erklärt (einschließlich Beispielcode).quelle
Schnelle Version:
(von https://stackoverflow.com/a/19132881/826435 )
In Ihrem View Controller passen Sie sich einfach einem Protokoll an und führen alle erforderlichen Aktionen aus:
Erstellen Sie dann beispielsweise eine Klasse
NavigationController+BackButton
und kopieren Sie einfach den folgenden Code:quelle
shouldPopOnBackButtonPress
sollte aufgerufen werden, solange es keine Bugs gibt.performSomeActionOnThePressOfABackButton
ist nur eine erfundene Methode, die es nicht gibt.performSomeActionOnThePressOfABackButton
in meinem Controller eine Methode erstellt , um eine bestimmte Aktion auszuführen, wenn die Zurück-Taste gedrückt wird, aber diese Methode wurde nie aufgerufen. Die Aktion ist eine normale RückgabeUINavigationController
, dienavigationBar.delegate
an die Navigationssteuerung eingestellt ist. Also sollten die Methoden aufgerufen werden. In Swift kann ich sie jedoch nicht dazu bringen, selbst in einer Unterklasse aufgerufen zu werden. Ich habe sie jedoch dazu gebracht, in Objective-C aufgerufen zu werden, daher würde ich vorerst nur die Objective-C-Version verwenden. Könnte ein schneller Fehler sein.Es ist nicht möglich, direkt zu tun. Es gibt ein paar Alternativen:
UIBarButtonItem
, die beim Tippen validiert und angezeigt wird, wenn der Test erfolgreich istUITextField
Delegatmethode, z. B.-textFieldShouldReturn:
die aufgerufen wird, nachdem die TasteReturn
oderDone
auf der Tastatur gedrückt wurdeDer Nachteil der ersten Option ist, dass auf den nach links zeigenden Pfeil der Zurück-Schaltfläche nicht über eine benutzerdefinierte Leistenschaltfläche zugegriffen werden kann. Sie müssen also ein Bild verwenden oder eine normale Stilschaltfläche verwenden.
Die zweite Option ist hilfreich, da Sie das Textfeld in der Delegate-Methode zurückerhalten, sodass Sie Ihre Validierungslogik auf das spezifische Textfeld ausrichten können, das an die Delegate-Rückrufmethode gesendet wird.
quelle
Aus einigen Threading-Gründen war die von @HansPinckaers erwähnte Lösung nicht richtig für mich, aber ich habe einen sehr einfacheren Weg gefunden, den Touch-Button zu berühren, und ich möchte dies hier festhalten, falls dies stundenlange Täuschungen vermeiden könnte jemand anderes. Der Trick ist wirklich einfach: Fügen Sie einfach einen transparenten UIButton als Unteransicht zu Ihrer UINavigationBar hinzu und stellen Sie Ihre Selektoren für ihn so ein, als wäre es die echte Schaltfläche! Hier ist ein Beispiel mit Monotouch und C #, aber die Übersetzung in Objective-C sollte nicht zu schwer zu finden sein.
Unterhaltsame Tatsache: Zu Testzwecken und um gute Abmessungen für meinen gefälschten Knopf zu finden, habe ich seine Hintergrundfarbe auf Blau gesetzt ... Und sie wird hinter dem Zurück-Knopf angezeigt! Wie auch immer, es fängt immer noch jede Berührung auf, die auf die ursprüngliche Taste abzielt.
quelle
Mit dieser Technik können Sie den Text der Schaltfläche "Zurück" ändern, ohne den Titel eines der Ansichts-Controller zu beeinflussen oder zu sehen, wie sich der Text der Schaltfläche "Zurück" während der Animation ändert.
Fügen Sie dies der init-Methode im aufrufenden View-Controller hinzu:
quelle
Einfachster Weg
Sie können die Delegatmethoden des UINavigationController verwenden. Die Methode
willShowViewController
wird aufgerufen, wenn die Zurück-Taste Ihres VC gedrückt wird. Tun Sie, was Sie wollen, wenn Sie die Zurück-Taste drückenquelle
Hier ist meine Swift-Lösung. Überschreiben Sie in Ihrer Unterklasse von UIViewController die Methode navigationShouldPopOnBackButton.
quelle
Es wurde eine Lösung gefunden, die auch den Stil der Zurück-Schaltfläche beibehält. Fügen Sie Ihrem View Controller die folgende Methode hinzu.
Stellen Sie nun eine Funktion bereit, die für die folgende Methode erforderlich ist:
Alles was es tut ist den hinteren Knopf mit einem transparenten Knopf abzudecken;)
quelle
=======================================
Aufbauend auf früheren Antworten mit UIAlert in Swift5 auf asynchrone Weise
Auf Ihrem Controller
quelle
Ich glaube nicht, dass dies leicht möglich ist. Ich glaube, der einzige Weg, dies zu umgehen, besteht darin, ein eigenes Pfeilbild mit der Zurück-Taste zu erstellen, um es dort oben zu platzieren. Anfangs war es für mich frustrierend, aber ich verstehe, warum es aus Gründen der Konsistenz weggelassen wurde.
Sie können schließen (ohne den Pfeil), indem Sie eine reguläre Schaltfläche erstellen und die Standard-Zurück-Schaltfläche ausblenden:
quelle
Es gibt einen einfacheren Weg, indem Sie einfach die Delegate-Methode von unterordnen
UINavigationBar
und die Methode überschreiben .ShouldPopItem
quelle
Die Lösung von onegray ist nicht sicher. Laut den offiziellen Dokumenten von Apple, https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html , sollten wir dies vermeiden.
"Wenn der Name einer in einer Kategorie deklarierten Methode mit einer Methode in der ursprünglichen Klasse oder einer Methode in einer anderen Kategorie in derselben Klasse (oder sogar einer Oberklasse) identisch ist, ist das Verhalten hinsichtlich der verwendeten Methodenimplementierung undefiniert zur Laufzeit. Dies ist weniger wahrscheinlich, wenn Sie Kategorien mit Ihren eigenen Klassen verwenden, kann jedoch Probleme verursachen, wenn Sie Kategorien verwenden, um Methoden zu Standardklassen von Cocoa oder Cocoa Touch hinzuzufügen. "
quelle
Verwenden von Swift:
quelle
Hier ist die Swift 3-Version von @oneways Antwort zum Abfangen des Ereignisses der Zurück-Schaltfläche der Navigationsleiste, bevor es ausgelöst wird. Da
UINavigationBarDelegate
dies nicht verwendet werden kannUIViewController
, müssen Sie einen Delegaten erstellen, der beimnavigationBar
shouldPop
Aufruf ausgelöst wird.Fügen Sie dann in Ihrem Ansichts-Controller die Delegatenfunktion hinzu:
Ich habe festgestellt, dass wir häufig einen Alarm-Controller hinzufügen möchten, damit Benutzer entscheiden können, ob sie zurückkehren möchten. Wenn ja, können Sie immer
return false
innavigationShouldPopOnBackButton()
Funktion und schließen Sie die View - Controller durch so etwas wie dies zu tun:quelle
Value of type 'UIViewController' has no member 'navigationShouldPopOnBackButton'
Wenn ich versuche, Ihren Code für die Zeile zu kompilieren, wirdif vc.responds(to: #selector(v...
auchself.topViewController
eine Option zurückgegeben, und es gibt auch eine Warnung dafür.let vc = self.topViewController as! MyViewController
und es scheint bisher gut zu funktionieren. Wenn Sie der Meinung sind, dass dies eine richtige Änderung ist, können Sie den Code bearbeiten. Wenn Sie der Meinung sind, dass dies nicht getan werden sollte, bin ich froh zu wissen, warum. Danke für diesen Code. Sie sollten wahrscheinlich einen Blog-Beitrag darüber schreiben, da diese Antwort gemäß den Stimmen vergraben ist.MyViewController
möglicherweise nicht konform sindBackButtonDelegate
. Anstatt das Auspacken zu erzwingen, sollten Sie dies tunguard let vc = self.topViewController as? MyViewController else { return true }
, um einen möglichen Absturz zu vermeiden.guard let vc = self.topViewController as? MyViewController else { self.popViewController(animated: true) return true }
um sicherzustellen, dass der Bildschirm auf die richtige Seite verschoben wird, falls er nicht richtig besetzt werden kann. Ich verstehe jetzt, dass dienavigationBar
Funktion in allen VCs aufgerufen wird und nicht nur im Viewcontroller, in dem dieser Code vorhanden ist. Vielleicht ist es auch gut, den Code in Ihrer Antwort zu aktualisieren? Vielen Dank.Swift 4 iOS 11.3 Version:
Dies baut auf der Antwort von kgaidis von https://stackoverflow.com/a/34343418/4316579 auf
Ich bin nicht sicher, wann die Erweiterung nicht mehr funktioniert, aber zum Zeitpunkt dieses Schreibens (Swift 4) scheint es, dass die Erweiterung nicht mehr ausgeführt wird, es sei denn, Sie erklären die UINavigationBarDelegate-Konformität wie unten beschrieben.
Ich hoffe, dies hilft Menschen, die sich fragen, warum ihre Erweiterung nicht mehr funktioniert.
quelle
Wenn Sie die Ziel- und Aktionsvariablen verwenden, die Sie derzeit 'nil' verlassen, sollten Sie in der Lage sein, Ihre Speicherdialoge so zu verkabeln, dass sie aufgerufen werden, wenn die Schaltfläche "ausgewählt" ist. Achtung, dies kann in seltsamen Momenten ausgelöst werden.
Ich stimme größtenteils mit Amagrammer überein, aber ich denke nicht, dass es so schwierig wäre, die Schaltfläche mit dem Pfeil benutzerdefiniert zu machen. Ich würde einfach die Zurück-Schaltfläche umbenennen, einen Screenshot machen, die benötigte Schaltflächengröße in Photoshop bearbeiten und das Bild oben auf Ihrer Schaltfläche haben.
quelle
Sie können versuchen, auf das Element "NavigationBars Right Button" zuzugreifen und dessen Selector-Eigenschaft festzulegen. Hier ist eine Referenz- UIBarButtonItem-Referenz . Wenn dies nicht funktioniert, setzen Sie das rechte Schaltflächenelement der Navigationsleiste auf ein benutzerdefiniertes UIBarButtonItem, das Sie verwenden erstelle und setze seinen Selektor ... hoffe das hilft
quelle
Für ein Formular, für das Benutzereingaben wie diese erforderlich sind, würde ich empfehlen, es als "modal" anstelle eines Teils Ihres Navigationsstapels aufzurufen. Auf diese Weise müssen sie sich um das Geschäft auf dem Formular kümmern, dann können Sie es validieren und über eine benutzerdefinierte Schaltfläche schließen. Sie können sogar eine Navigationsleiste entwerfen, die genauso aussieht wie der Rest Ihrer App, Ihnen jedoch mehr Kontrolle bietet.
quelle
Um die Schaltfläche Zurück abzufangen, bedecken Sie sie einfach mit einem transparenten UIControl und fangen Sie die Berührungen ab.
quelle
Zumindest in Xcode 5 gibt es eine einfache und ziemlich gute (nicht perfekte) Lösung. Ziehen Sie in IB ein Balkenschaltflächenelement aus dem Bereich "Dienstprogramme" und legen Sie es auf der linken Seite der Navigationsleiste ab, wo sich die Schaltfläche "Zurück" befinden würde. Setzen Sie das Etikett auf "Zurück". Sie haben eine funktionierende Schaltfläche, die Sie mit Ihrer IBAction verknüpfen und Ihren viewController schließen können. Ich mache etwas Arbeit und löse dann einen Abwicklungssegment aus und es funktioniert perfekt.
Was nicht ideal ist, ist, dass diese Schaltfläche nicht den Pfeil <erhält und den vorherigen VCs-Titel nicht weitergibt, aber ich denke, dies kann verwaltet werden. Für meine Zwecke habe ich die neue Schaltfläche "Zurück" als "Fertig" festgelegt, damit der Zweck klar ist.
Sie haben auch zwei Zurück-Schaltflächen im IB-Navigator, die Sie jedoch aus Gründen der Übersichtlichkeit leicht beschriften können.
quelle
Schnell
quelle
Dieser Ansatz hat bei mir funktioniert (aber die Schaltfläche "Zurück" hat nicht das Zeichen "<"):
quelle
Schnelle Version von @ onegrays Antwort
Passen Sie sich jetzt in jedem Controller einfach an
RequestsNavigationPopVerification
und dieses Verhalten wird standardmäßig übernommen.quelle
Verwenden
isMovingFromParentViewController
quelle
viewDidDisappear
. Auf diese Weise wird es nur ausgelöst, wenn die Ansicht definitiv verschwunden ist.Die Antwort von @William ist jedoch richtig. Wenn der Benutzer eine Swipe-to-Go-Back-Geste startet, wird die
viewWillDisappear
Methode aufgerufen und befindetself
sich nicht im Navigationsstapel ( dhself.navigationController.viewControllers
nicht enthaltenself
), selbst wenn der Swipe ausgeführt wird ist nicht abgeschlossen und der Ansichts-Controller ist nicht tatsächlich geöffnet. Die Lösung wäre also:Deaktivieren Sie die Wisch-zu-Zurück-Geste in
viewDidAppear
und erlauben Sie nur die Verwendung der Zurück-Taste, indem Sie Folgendes verwenden:Oder verwenden Sie
viewDidDisappear
stattdessen einfach wie folgt:quelle
Die Lösung, die ich bisher gefunden habe, ist nicht sehr schön, aber sie funktioniert für mich. Mit dieser Antwort überprüfe ich auch, ob ich programmgesteuert auftauche oder nicht:
Sie müssen diese Eigenschaft zu Ihrem Controller hinzufügen und auf YES setzen, bevor Sie programmgesteuert einspringen:
quelle
Neue Möglichkeit gefunden:
Ziel c
Schnell
quelle