it-swarm.com.de

Einstellungsaktion für die Zurück-Taste im Navigations-Controller

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 ihm über das Attribut backbutton zugewiesen wird, dass es nicht beachtet und nur die aktuelle Ansicht öffnet und zum Stammverzeichnis 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 dem navigationItem gesetzt habe, ruft es meine Aktion auf, aber dann sieht die Schaltfläche wie eine einfache runde aus, anstatt wie die mit einem Pfeil versehene hintere:

self.navigationItem.leftBarButtonItem = backButton;

Wie kann ich meine benutzerdefinierte Aktion aufrufen, bevor ich zur Stammansicht zurückkehre? Gibt es eine Möglichkeit, die Standard-Zurück-Aktion zu überschreiben, oder gibt es eine Methode, die beim Verlassen einer Ansicht immer aufgerufen wird (viewDidUnload macht das nicht)?

177
Parrots

Versuchen Sie, dies in den View-Controller zu stellen, in dem Sie die Presse erkennen möchten:

-(void) viewWillDisappear:(BOOL)animated {
    if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
       // back button was pressed.  We know this is true because self is no longer
       // in the navigation stack.  
    }
    [super viewWillDisappear:animated];
}
363

Ich habe die Erweiterung IViewController-BackButtonHandler implementiert. Es muss nichts untergeordnet werden. Fügen Sie es einfach in Ihr Projekt ein und überschreiben Sie die navigationShouldPopOnBackButton -Methode in der UIViewController -Klasse:

-(BOOL) navigationShouldPopOnBackButton {
    if(needsShowConfirmation) {
        // Show confirmation alert
        // ...
        return NO; // Ignore 'Back' button this time
    }
    return YES; // Process 'Back' button click and Pop view controler
}

Beispiel-App herunterladen .

174
onegray

Anders als Amagrammer sagte, ist es möglich. Sie müssen Ihre navigationController unterklassifizieren. Ich habe alles erklärt hier (einschließlich Beispielcode).

42
HansPinckaers

Schnelle Version:

(von https://stackoverflow.com/a/19132881/826435 )

In Ihrem View Controller richten Sie sich einfach nach einem Protokoll und führen die erforderlichen Aktionen aus:

extension MyViewController: NavigationControllerBackButtonDelegate {
    func shouldPopOnBackButtonPress() -> Bool {
        performSomeActionOnThePressOfABackButton()
        return false
    }
}

Dann erstelle eine Klasse, sag NavigationController+BackButton, und fügen Sie einfach den folgenden Code ein:

protocol NavigationControllerBackButtonDelegate {
    func shouldPopOnBackButtonPress() -> Bool
}

extension UINavigationController {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        // Prevents from a synchronization issue of popping too many navigation items
        // and not enough view controllers or viceversa from unusual tapping
        if viewControllers.count < navigationBar.items!.count {
            return true
        }

        // Check if we have a view controller that wants to respond to being popped
        var shouldPop = true
        if let viewController = topViewController as? NavigationControllerBackButtonDelegate {
            shouldPop = viewController.shouldPopOnBackButtonPress()
        }

        if (shouldPop) {
            DispatchQueue.main.async {
                self.popViewController(animated: true)
            }
        } else {
            // Prevent the back button from staying in an disabled state
            for view in navigationBar.subviews {
                if view.alpha < 1.0 {
                    UIView.animate(withDuration: 0.25, animations: {
                        view.alpha = 1.0
                    })
                }
            }

        }

        return false
    }
}
13
kgaidis

Aus Threading-Gründen stimmte die von @HansPinckaers erwähnte Lösung nicht mit mir überein, aber ich fand eine sehr einfache Möglichkeit, den Zurück-Button zu berühren, und ich möchte dies hier festhalten, um stundenlange Täuschungen zu vermeiden jemand anderes. Der Trick ist ganz einfach: Fügen Sie Ihrer UINavigationBar einfach einen transparenten UIButton als Unteransicht 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 nach Objective-C sollte nicht allzu schwer zu finden sein.

public class Test : UIViewController {
    public override void ViewDidLoad() {
        UIButton b = new UIButton(new RectangleF(0, 0, 60, 44)); //width must be adapted to label contained in button
        b.BackgroundColor = UIColor.Clear; //making the background invisible
        b.Title = string.Empty; // and no need to write anything
        b.TouchDown += delegate {
            Console.WriteLine("caught!");
            if (true) // check what you want here
                NavigationController.PopViewControllerAnimated(true); // and then we pop if we want
        };
        NavigationController.NavigationBar.AddSubview(button); // insert the button to the nav bar
    }
}

Unterhaltsame Tatsache: Zu Testzwecken und um gute Abmessungen für meinen gefälschten Knopf zu finden, habe ich seine Hintergrundfarbe auf blau gesetzt ... Und es zeigt hinten den Zurück-Knopf! Wie dem auch sei, es fängt immer noch jede Berührung auf, die auf den ursprünglichen Knopf zielt.

5
psycho

Es ist nicht möglich, direkt zu tun. Es gibt ein paar Alternativen:

  1. Erstellen Sie Ihr eigenes benutzerdefiniertes UIBarButtonItem, das bei Bestehen des Tests überprüft und angezeigt wird
  2. Überprüfen Sie den Inhalt des Formularfelds mit einer UITextField -Delegatemethode, z. B. -textFieldShouldReturn: , der aufgerufen wird, nachdem die Taste Return oder Done auf der Tastatur gedrückt wurde

Der Nachteil der ersten Option ist, dass der Linkspfeil der Zurück-Schaltfläche nicht über eine benutzerdefinierte Leistenschaltfläche aufgerufen werden kann. Sie müssen also ein Bild verwenden oder eine normale Stilschaltfläche verwenden.

Die zweite Option ist Nice, da Sie das Textfeld in der Delegate-Methode zurückerhalten, sodass Sie Ihre Validierungslogik auf das bestimmte Textfeld ausrichten können, das an die Delegate-Call-Back-Methode gesendet wird.

5
Alex Reynolds

Mit dieser Technik können Sie den Text der Schaltfläche "Zurück" ändern, ohne den Titel eines der Ansichtscontroller 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 View-Controller aufrufend hinzu:

UIBarButtonItem *temporaryBarButtonItem = [[UIBarButtonItem alloc] init];   
temporaryBarButtonItem.title = @"Back";
self.navigationItem.backBarButtonItem = temporaryBarButtonItem;
[temporaryBarButtonItem release];
3
Jason Moore

Es wurde eine Lösung gefunden, die den Stil des Zurück-Buttons beibehält. Fügen Sie Ihrem Ansichtscontroller die folgende Methode hinzu.

-(void) overrideBack{

    UIButton *transparentButton = [[UIButton alloc] init];
    [transparentButton setFrame:CGRectMake(0,0, 50, 40)];
    [transparentButton setBackgroundColor:[UIColor clearColor]];
    [transparentButton addTarget:self action:@selector(backAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.navigationController.navigationBar addSubview:transparentButton];


}

Stellen Sie nun nach Bedarf eine Funktionalität für die folgende Methode bereit:

-(void)backAction:(UIBarButtonItem *)sender {
    //Your functionality
}

Alles was es macht ist, den Zurück-Knopf mit einem transparenten Knopf zu bedecken;)

3
Sarasranglt

Einfachster Weg

Sie können die Delegatmethoden des UINavigationControllers verwenden. Die Methode willShowViewController wird aufgerufen, wenn die Zurück-Taste Ihres VC) gedrückt wird

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
3
Xar E Ahmer

Es gibt einen einfacheren Weg, indem Sie einfach die Delegate-Methode der UINavigationBar und Override der ShouldPopItemMethode unterordnen.

2
jazzyjef2002

Hier ist Swift 3 Version von @ oneway 's Antwort, um das Zurück-Button-Ereignis der Navigationsleiste abzufangen, bevor es ausgelöst wird. Da UINavigationBarDelegate nicht verwendet werden kann UIViewController, Sie müssen einen Delegaten erstellen, der ausgelöst wird, wenn navigationBarshouldPop aufgerufen wird.

@objc public protocol BackButtonDelegate {
      @objc optional func navigationShouldPopOnBackButton() -> Bool 
}

extension UINavigationController: UINavigationBarDelegate  {

    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {

        if viewControllers.count < (navigationBar.items?.count)! {                
            return true
        }

        var shouldPop = true
        let vc = self.topViewController

        if vc.responds(to: #selector(vc.navigationShouldPopOnBackButton)) {
            shouldPop = vc.navigationShouldPopOnBackButton()
        }

        if shouldPop {
            DispatchQueue.main.async {
                self.popViewController(animated: true)
            }
        } else {
            for subView in navigationBar.subviews {
                if(0 < subView.alpha && subView.alpha < 1) {
                    UIView.animate(withDuration: 0.25, animations: {
                        subView.alpha = 1
                    })
                }
            }
        }

        return false
    }
}

Fügen Sie dann in Ihrem Ansichtscontroller die Delegatfunktion hinzu:

class BaseVC: UIViewController, BackButtonDelegate {
    func navigationShouldPopOnBackButton() -> Bool {
        if ... {
            return true
        } else {
            return false
        }        
    }
}

Ich habe festgestellt, dass wir häufig einen Warnungs-Controller hinzufügen möchten, damit Benutzer entscheiden können, ob sie zurückkehren möchten. In diesem Fall können Sie in navigationShouldPopOnBackButton() immer return false Eingeben und Ihren View-Controller schließen, indem Sie wie folgt vorgehen:

func navigationShouldPopOnBackButton() -> Bool {
     let alert = UIAlertController(title: "Warning",
                                          message: "Do you want to quit?",
                                          preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { UIAlertAction in self.yes()}))
            alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { UIAlertAction in self.no()}))
            present(alert, animated: true, completion: nil)
      return false
}

func yes() {
     print("yes")
     DispatchQueue.main.async {
            _ = self.navigationController?.popViewController(animated: true)
        }
}

func no() {
    print("no")       
}
2
Lawliet

Ich glaube nicht, dass dies einfach möglich ist. Der einzige Weg, wie ich glaube, dies zu umgehen, besteht darin, ein eigenes Pfeilbild mit dem Zurück-Knopf zu erstellen, um es dort oben zu platzieren. Anfangs war es frustrierend für mich, aber ich verstehe, warum es aus Gründen der Beständigkeit 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:

self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Servers" style:UIBarButtonItemStyleDone target:nil action:nil] autorelease];
self.navigationItem.hidesBackButton = YES;
2
Meltemi

Swift benutzen:

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    if self.navigationController?.topViewController != self {
        print("back button tapped")
    }
}
2
Murray Sagal

die Lösung von onegray ist nicht sicher. Gemäß den offiziellen Dokumenten von Apple https://developer.Apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html , we sollte das 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 Superklasse) identisch ist, ist das Verhalten hinsichtlich der verwendeten Methodenimplementierung undefiniert Dies ist weniger wahrscheinlich, wenn Sie Kategorien mit eigenen Klassen verwenden, kann jedoch Probleme verursachen, wenn Sie Kategorien verwenden, um Methoden zu Standard-Cocoa- oder Cocoa Touch-Klassen hinzuzufügen. "

2
user2612791

Hier ist meine Swift Lösung. Überschreiben Sie in Ihrer Unterklasse von UIViewController die navigationShouldPopOnBackButton-Methode.

extension UIViewController {
    func navigationShouldPopOnBackButton() -> Bool {
        return true
    }
}

extension UINavigationController {

    func navigationBar(navigationBar: UINavigationBar, shouldPopItem item: UINavigationItem) -> Bool {
        if let vc = self.topViewController {
            if vc.navigationShouldPopOnBackButton() {
                self.popViewControllerAnimated(true)
            } else {
                for it in navigationBar.subviews {
                    let view = it as! UIView
                    if view.alpha < 1.0 {
                        [UIView .animateWithDuration(0.25, animations: { () -> Void in
                            view.alpha = 1.0
                        })]
                    }
                }
                return false
            }
        }
        return true
    }

}
2
AutomatonTec

Die Antwort von @William ist jedoch richtig. Wenn der Benutzer eine Swipe-to-Go-Back-Geste startet, wird die viewWillDisappear -Methode aufgerufen und sogar self wird nicht im Navigationsstapel (das) angezeigt ist, self.navigationController.viewControllers enthält self) nicht, auch wenn das Wischen nicht abgeschlossen ist und der Ansichtscontroller nicht tatsächlich eingeblendet ist. Die Lösung wäre also:

  1. Deaktivieren Sie die Swipe-to-Go-Back-Geste in viewDidAppear und erlauben Sie nur die Verwendung der Zurück-Schaltfläche, indem Sie Folgendes verwenden:

    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
    {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    }
    
  2. Oder verwenden Sie stattdessen einfach viewDidDisappear wie folgt:

    - (void)viewDidDisappear:(BOOL)animated
    {
        [super viewDidDisappear:animated];
        if (![self.navigationController.viewControllers containsObject:self])
        {
            // back button was pressed or the the swipe-to-go-back gesture was
            // completed. We know this is true because self is no longer
            // in the navigation stack.
        }
    }
    
1
boherna

Dieser Ansatz hat bei mir funktioniert (aber der "Zurück" -Button hat kein "<" -Zeichen):

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIBarButtonItem* backNavButton = [[UIBarButtonItem alloc] initWithTitle:@"Back"
                                                                      style:UIBarButtonItemStyleBordered
                                                                     target:self
                                                                     action:@selector(backButtonClicked)];
    self.navigationItem.leftBarButtonItem = backNavButton;
}

-(void)backButtonClicked
{
    // Do something...
    AppDelegate* delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
    [delegate.navController popViewControllerAnimated:YES];
}
1
Ivan

Benutze isMovingFromParentViewController

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(true)

    if self.isMovingFromParentViewController {
        // current viewController is removed from parent
        // do some work
    }
}
1
herrk

Für ein Formular, das Benutzereingaben wie diese erfordert, 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, aber Ihnen mehr Kontrolle gibt.

1
Travis M.

Sie können versuchen, auf das Element NavigationBars Right Button zuzugreifen und dessen Auswahleigenschaft festzulegen. Hier ist eine Referenz UIBarButtonItem-Referenz Arbeit ist, setzen Sie die rechte Schaltfläche der Navigationsleiste auf ein benutzerdefiniertes UIBarButtonItem, das Sie erstellen und dessen Auswahl festlegen ... hoffe, dies hilft

1
Daniel

Um die Zurück-Taste abzufangen, bedecken Sie sie einfach mit einer transparenten UIControl und fangen Sie die Berührungen ab.

@interface MyViewController : UIViewController
{
    UIControl   *backCover;
    BOOL        inhibitBackButtonBOOL;
}
@end

@implementation MyViewController
-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    // Cover the back button (cannot do this in viewWillAppear -- too soon)
    if ( backCover == nil ) {
        backCover = [[UIControl alloc] initWithFrame:CGRectMake( 0, 0, 80, 44)];
#if TARGET_IPHONE_SIMULATOR
        // show the cover for testing
        backCover.backgroundColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.15];
#endif
        [backCover addTarget:self action:@selector(backCoverAction) forControlEvents:UIControlEventTouchDown];
        UINavigationBar *navBar = self.navigationController.navigationBar;
        [navBar addSubview:backCover];
    }
}

-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [backCover removeFromSuperview];
    backCover = nil;
}

- (void)backCoverAction
{
    if ( inhibitBackButtonBOOL ) {
        NSLog(@"Back button aborted");
        // notify the user why...
    } else {
        [self.navigationController popViewControllerAnimated:YES]; // "Back"
    }
}
@end
1
Jeff

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 aufgehört hat zu funktionieren, 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.

Hoffe, dies hilft Menschen, die sich fragen, warum ihre Erweiterung nicht mehr funktioniert.

extension UINavigationController: UINavigationBarDelegate {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {

    }
}
1
Edward L.

Zumindest in Xcode 5 gibt es eine einfache und ziemlich gute (nicht perfekte) Lösung. Ziehen Sie in IB ein Element der Leistenschaltfläche 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 die Beschriftung auf "Zurück". Sie haben eine funktionierende Schaltfläche, die Sie an Ihre IBAction binden und Ihren viewController schließen können. Ich mache ein bisschen Arbeit und löse dann einen Abwicklungssegue aus und es funktioniert perfekt.

Was nicht ideal ist, ist, dass diese Schaltfläche nicht den <-Pfeil erhält und den vorherigen VC-Titel nicht überträgt, aber ich denke, dass dies verwaltet werden kann. Für meine Zwecke habe ich die neue Schaltfläche "Zurück" auf "Fertig" gesetzt, damit ihr Zweck klar ist.

Sie haben auch zwei Zurück-Schaltflächen im IB-Navigator, die Sie jedoch der Übersichtlichkeit halber leicht beschriften können.

enter image description here

1
Dan Loughney

Wenn Sie die Ziel- und Aktionsvariablen verwenden, die Sie gerade als 'nil' deklarieren, sollten Sie in der Lage sein, Ihre Speicherdialoge so zu verknüpfen, dass sie aufgerufen werden, wenn die Schaltfläche "ausgewählt" ist. Achtung, dies kann in seltsamen Momenten ausgelöst werden.

Ich stimme größtenteils Amagrammer zu, aber ich denke nicht, dass es so schwierig wäre, den Knopf mit dem Pfeil zu erstellen. Ich würde einfach die Schaltfläche "Zurück" umbenennen, einen Screenshot machen, die erforderliche Schaltflächengröße in Photoshop festlegen und das Bild oben auf der Schaltfläche anzeigen.

1
TahoeWolverine

Swift

override func viewWillDisappear(animated: Bool) {
    let viewControllers = self.navigationController?.viewControllers!
    if indexOfArray(viewControllers!, searchObject: self) == nil {
        // do something
    }
    super.viewWillDisappear(animated)
}

func indexOfArray(array:[AnyObject], searchObject: AnyObject)-> Int? {
    for (index, value) in enumerate(array) {
        if value as UIViewController == searchObject as UIViewController {
            return index
        }
    }
    return nil
}
1
zono

Einen neuen Weg gefunden:

Ziel c

- (void)didMoveToParentViewController:(UIViewController *)parent{
    if (parent == NULL) {
        NSLog(@"Back Pressed");
    }
}

Swift

override func didMoveToParentViewController(parent: UIViewController?) {
    if parent == nil {
        println("Back Pressed")
    }
}
0
Ashish Kakkad

Die Lösung, die ich bisher gefunden habe, ist nicht sehr schön, aber es funktioniert für mich. Unter Berücksichtigung dieser Antwort überprüfe ich auch, ob ich programmgesteuert poppe oder nicht:

- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];

  if ((self.isMovingFromParentViewController || self.isBeingDismissed)
      && !self.isPoppingProgrammatically) {
    // Do your stuff here
  }
}

Sie müssen diese Eigenschaft zu Ihrem Controller hinzufügen und auf YES setzen, bevor Sie programmgesteuert aufspringen:

self.isPoppingProgrammatically = YES;
[self.navigationController popViewControllerAnimated:YES];
0
Ferran Maylinch

Aufbauend auf vorherigen Antworten mit IAlert in Swift5 in Asynchronous Weise


protocol NavigationControllerBackButtonDelegate {
    func shouldPopOnBackButtonPress(_ completion: @escaping (Bool) -> ())
}

extension UINavigationController: UINavigationBarDelegate {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {

        if viewControllers.count < navigationBar.items!.count {
            return true
        }

        // Check if we have a view controller that wants to respond to being popped

        if let viewController = topViewController as? NavigationControllerBackButtonDelegate {

            viewController.shouldPopOnBackButtonPress { shouldPop in
                if (shouldPop) {
                    /// on confirm => pop
                    DispatchQueue.main.async {
                        self.popViewController(animated: true)
                    }
                } else {
                    /// on cancel => do nothing
                }
            }
            /// return false => so navigator will cancel the popBack
            /// until user confirm or cancel
            return false
        }else{
            DispatchQueue.main.async {
                self.popViewController(animated: true)
            }
        }
        return true
    }
}


Auf Ihrem Controller


extension MyController: NavigationControllerBackButtonDelegate {

    func shouldPopOnBackButtonPress(_ completion: @escaping (Bool) -> ()) {

        let msg = "message"

        /// show UIAlert
        alertAttention(msg: msg, actions: [

            .init(title: "Continuer", style: .destructive, handler: { _ in
                completion(true)
            }),
            .init(title: "Annuler", style: .cancel, handler: { _ in
                completion(false)
            })
            ])

    }

}
0
brahimm

Schnelle Version von @ onegrays Antwort

protocol RequestsNavigationPopVerification {
    var confirmationTitle: String { get }
    var confirmationMessage: String { get }
}

extension RequestsNavigationPopVerification where Self: UIViewController {
    var confirmationTitle: String {
        return "Go back?"
    }

    var confirmationMessage: String {
        return "Are you sure?"
    }
}

final class NavigationController: UINavigationController {

    func navigationBar(navigationBar: UINavigationBar, shouldPopItem item: UINavigationItem) -> Bool {

        guard let requestsPopConfirm = topViewController as? RequestsNavigationPopVerification else {
            popViewControllerAnimated(true)
            return true
        }

        let alertController = UIAlertController(title: requestsPopConfirm.confirmationTitle, message: requestsPopConfirm.confirmationMessage, preferredStyle: .Alert)

        alertController.addAction(UIAlertAction(title: "Cancel", style: .Cancel) { _ in
            dispatch_async(dispatch_get_main_queue(), {
                let dimmed = navigationBar.subviews.flatMap { $0.alpha < 1 ? $0 : nil }
                UIView.animateWithDuration(0.25) {
                    dimmed.forEach { $0.alpha = 1 }
                }
            })
            return
        })

        alertController.addAction(UIAlertAction(title: "Go back", style: .Default) { _ in
            dispatch_async(dispatch_get_main_queue(), {
                self.popViewControllerAnimated(true)
            })
        })

        presentViewController(alertController, animated: true, completion: nil)

        return false
    }
}

Jetzt müssen Sie in jedem Controller nur noch RequestsNavigationPopVerification eingeben, und dieses Verhalten wird standardmäßig übernommen.

0
Adam Waite