Ich muss erkennen, wann der Benutzer auf die Schaltfläche "Zurück" in der Navigationsleiste tippt, um in diesem Fall einige Vorgänge auszuführen. Ich versuche, eine Aktion auf diese Schaltfläche manuell festzulegen:
[self.navigationItem.backBarButtonItem setAction:@selector(performBackNavigation:)];
- (void)performBackNavigation:(id)sender
{
// Do operations
[self.navigationController popViewControllerAnimated:NO];
}
Ich habe diesen Code zuerst im Ansichts-Controller selbst platziert, aber ich habe festgestellt, dass dies self.navigationItem.backBarButtonItem
der Fall zu sein scheint nil
. Deshalb habe ich denselben Code in den übergeordneten Ansichts-Controller verschoben, wodurch der erstere in den Navigationsstapel verschoben wird. Aber ich kann es auch nicht zum Laufen bringen. Ich habe einige Beiträge zu diesem Problem gelesen und einige sagten, dass der Selektor auf dem übergeordneten Ansichts-Controller eingestellt werden muss, aber für mich funktioniert es sowieso nicht ... Was könnte ich falsch machen?
Vielen Dank
UINavigationControllerDelegate
.Antworten:
Versuchen Sie diesen Code mithilfe einer
VIewWillDisappear
Methode, um das Drücken der Zurück-Taste von NavigationItem zu erkennen:-(void) viewWillDisappear:(BOOL)animated { if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) { // Navigation button was pressed. Do some stuff [self.navigationController popViewControllerAnimated:NO]; } [super viewWillDisappear:animated]; }
ODER Es gibt eine andere Möglichkeit, die Aktion der Navigationsrücktaste abzurufen.
Schaltfläche "Benutzerdefiniert" für UINavigationItem der Schaltfläche "Zurück" erstellen.
Zum Beispiel:
- (void)viewDidLoad { [super viewDidLoad]; UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:@"Home" style:UIBarButtonItemStyleBordered target:self action:@selector(home:)]; self.navigationItem.leftBarButtonItem=newBackButton; } -(void)home:(UIBarButtonItem *)sender { [self.navigationController popToRootViewControllerAnimated:YES]; }
Swift:
override func willMoveToParentViewController(parent: UIViewController?) { if parent == nil { // Back btn Event handler } }
quelle
Schnell
override func didMoveToParentViewController(parent: UIViewController?) { if parent == nil { //"Back pressed" } }
quelle
Vielleicht passt diese Antwort nicht zu Ihrer Erklärung, sondern zum Titel der Frage. Dies ist nützlich, wenn Sie wissen möchten, wann Sie die Zurück-Taste auf einem gedrückt haben
UINavigationBar
.In diesem Fall können Sie das
UINavigationBarDelegate
Protokoll verwenden und eine der folgenden Methoden implementieren:- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item; - (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;
Wenn die
didPopItem
Methode aufgerufen wird, haben Sie entweder die Zurück-Taste gedrückt oder Sie haben sie verwendet[UINavigationBar popNavigationItemAnimated:]
Methode , und die Navigationsleiste hat das Element eingeblendet.Nun, wenn Sie wissen möchten, welche Aktion die ausgelöst hat
didPopItem
Methode hat, können Sie ein Flag verwenden.Bei diesem Ansatz muss ich kein Schaltflächenelement in der linken Leiste mit einem Pfeilbild manuell hinzufügen, um es der iOS-Zurück-Schaltfläche ähnlich zu machen und mein benutzerdefiniertes Ziel / meine benutzerdefinierte Aktion festlegen zu können.
Sehen wir uns ein Beispiel an:
Ich habe einen Ansichts-Controller mit einem Seitenansichts-Controller und eine benutzerdefinierte Seitenanzeige-Ansicht. Ich verwende auch eine benutzerdefinierte UINavigationBar, um einen Titel anzuzeigen, um zu wissen, auf welcher Seite ich bin, und die Schaltfläche "Zurück", um zur vorherigen Seite zurückzukehren. Außerdem kann ich auf dem Seiten-Controller zur vorherigen / nächsten Seite wischen.
#pragma mark - UIPageViewController Delegate Methods - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed { if( completed ) { //... if( currentIndex > lastIndex ) { UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"Some page title"]; [[_someViewController navigationBar] pushNavigationItem:navigationItem animated:YES]; [[_someViewController pageControl] setCurrentPage:currentIndex]; } else { _autoPop = YES; //We pop the item automatically from code. [[_someViewController navigationBar] popNavigationItemAnimated:YES]; [[_someViewController pageControl] setCurrentPage:currentIndex]; } } }
Dann implementiere ich UINavigationBar-Delegatenmethoden:
#pragma mark - UINavigationBar Delegate Methods - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item { if( !_autoPop ) { //Pop by back button tap } else { //Pop from code } _autoPop = NO; return YES; }
In diesem Fall habe ich verwendet,
shouldPopItem
weil der Pop animiert ist und ich die Zurück-Taste sofort bedienen und nicht warten wollte, bis der Übergang abgeschlossen ist.quelle
Das Problem mit
didMoveToParentViewController
dabei ist, dass es aufgerufen wird, sobald die übergeordnete Ansicht wieder vollständig sichtbar ist. Wenn Sie also vorher einige Aufgaben ausführen müssen, funktioniert es nicht.Und es funktioniert nicht mit der gesteuerten Animationsgeste. Verwenden
willMoveToParentViewController
funktioniert besser.Ziel c
- (void)willMoveToParentViewController:(UIViewController *)parent{ if (parent == NULL) { // ... } }
Schnell
override func willMoveToParentViewController(parent: UIViewController?) { if parent == nil { // ... } }
quelle
Dies ist die Objective-C-Version von Dadachis Antwort:
Ziel c
- (void)didMoveToParentViewController:(UIViewController *)parent{ if (parent == NULL) { NSLog(@"Back Pressed"); } }
quelle
Legen Sie den Delegaten der UINavigationBar fest und verwenden Sie dann:
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item { //handle the action here }
quelle
UINavigationController
die Navigationsleiste mit a verwalten, führt der Versuch, den Delegaten festzulegen, zu einer Ausnahme: "*** Beenden der App aufgrund der nicht erfassten Ausnahme 'NSInternalInconsistencyException', Grund: 'Der Delegat kann nicht manuell in einer von einem Controller verwalteten UINavigationBar festgelegt werden. '". DasUINavigationController
ist der Delegierte. Dies bedeutet, dass Sie den Controller unterklassifizieren und dieUINavigationBarDelegate
Methoden überschreiben können (wahrscheinlich Super aufrufen).UINavigationController
jedoch nicht direkt aufrufen, da es nicht öffentlich konform istUINavigationBarDelegate
, was zu einem Compilerfehler führt! Möglicherweise gibt es eine Lösung mitUINavigationControllerDelegate
.Keine der anderen Lösungen hat bei mir funktioniert, aber das tut:
Erstellen Sie Ihre eigene Unterklasse von UINavigationController, lassen Sie UINavigationBarDelegate implementieren (der Delegat der Navigationsleiste muss nicht manuell festgelegt werden), fügen Sie eine UIViewController-Erweiterung hinzu, die eine Methode definiert, die beim Drücken einer Zurück-Taste aufgerufen werden soll, und implementieren Sie diese Methode dann in Ihrer UINavigationController-Unterklasse ::
func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool { self.topViewController?.methodToBeCalledOnBackButtonPress() self.popViewController(animated: true) return true }
quelle
In Swift 4 oder höher:
override func didMove(toParent parent: UIViewController?) { if parent == nil { //"Back pressed" } }
quelle
Legen Sie das UINavigationControllerDelegate fest und implementieren Sie diese Delegatenfunktion (Swift):
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) { if viewController is <target class> { //if the only way to get back - back button was pressed } }
quelle
Verwenden Sie eine benutzerdefinierte
UINavigationController
Unterklasse, die das implementiertshouldPop
Methode .In Swift:
class NavigationController: UINavigationController, UINavigationBarDelegate { var shouldPopHandler: (() -> Bool)? func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool { if let shouldPopHandler = self.shouldPopHandler, !shouldPopHandler() { return false } self.popViewController(animated: true) // Needed! return true } }
Wenn eingestellt, wird Ihr
shouldPopHandler()
ist, werden Sie aufgerufen, um zu entscheiden, ob der Controller aktiviert sein soll oder nicht. Wenn es nicht eingestellt ist, wird es wie gewohnt geknallt.Es ist eine gute Idee,
UINavigationController
s zu deaktivieren,interactivePopGestureRecognizer
da die Geste Ihren Handler sonst nicht aufruft.quelle