Umieściłem widok na kontrolerze nawigacyjnym i po naciśnięciu przycisku Wstecz automatycznie przechodzi do poprzedniego widoku. Chcę zrobić kilka rzeczy, gdy przycisk Wstecz zostanie naciśnięty przed usunięciem widoku ze stosu. Jaka jest funkcja wywołania zwrotnego przycisku Wstecz?
102
Odpowiedzi:
Williama Jockusch za odpowiedź rozwiązać ten problem z łatwym sztuczki.
źródło
Moim zdaniem najlepsze rozwiązanie.
Ale działa tylko z iOS5 +
źródło
Prawdopodobnie lepiej jest zastąpić przycisk Backbutton, aby móc obsłużyć zdarzenie przed wyświetleniem widoku na takie rzeczy, jak potwierdzenie użytkownika.
in viewDidLoad utwórz UIBarButtonItem i ustaw self.navigationItem.leftBarButtonItem na przekazanie w sel
Następnie możesz wykonać takie czynności, jak podniesienie UIAlertView, aby potwierdzić akcję, a następnie wyświetlenie kontrolera widoku itp.
Lub zamiast tworzyć nowy przycisk Backbutton, można dostosować metody delegata UINavigationController do wykonywania akcji po naciśnięciu przycisku Wstecz.
źródło
UINavigationControllerDelegate
Nie ma metod, które są wywoływane gdy back-przycisk jest na podsłuchu.To jest właściwy sposób, aby to wykryć.
ta metoda jest wywoływana również wtedy, gdy przekazywany jest widok. Zatem sprawdzenie parent == nil służy do wyrzucenia kontrolera widoku ze stosu
źródło
Skończyłem z takimi rozwiązaniami. Gdy stukamy przycisk wstecz, wywoływana jest metoda viewDidDisappear. możemy sprawdzić, wywołując selektor isMovingFromParentViewController, który zwraca wartość true. możemy przekazać dane z powrotem (używając Delegata). Mam nadzieję, że to komuś pomoże.
źródło
[super viewDidDisappear:animated]
Może jest już trochę za późno, ale chciałem też wcześniej takiego zachowania. Rozwiązanie, które wybrałem, działa całkiem dobrze w jednej z aplikacji obecnie dostępnych w App Store. Ponieważ nie widziałem nikogo, kto stosuje podobną metodę, chciałbym się nią tutaj podzielić. Wadą tego rozwiązania jest to, że wymaga podklasy
UINavigationController
. Chociaż użycie Method Swizzling może pomóc w uniknięciu tego, nie posunąłem się tak daleko.Tak więc domyślny przycisk Wstecz jest faktycznie zarządzany przez
UINavigationBar
. Gdy użytkownik naciśnie przycisk Wstecz,UINavigationBar
zapytaj delegata, czy powinien otworzyć górną częśćUINavigationItem
, dzwoniącnavigationBar(_:shouldPop:)
.UINavigationController
faktycznie implementuje to, ale nie deklaruje publicznie, że przyjmujeUINavigationBarDelegate
(dlaczego !?). Aby przechwycić to zdarzenie, utwórz podklasęUINavigationController
, zadeklaruj jej zgodnośćUINavigationBarDelegate
i zaimplementujnavigationBar(_:shouldPop:)
. Zwróć,true
jeśli górny element powinien zostać usunięty. Wróć,false
jeśli powinno zostać.Są dwa problemy. Po pierwsze, musisz kiedyś wywołać
UINavigationController
wersję programunavigationBar(_:shouldPop:)
. AleUINavigationBarController
nie deklaruje publicznie, że jest zgodny zUINavigationBarDelegate
, próba wywołania spowoduje błąd czasu kompilacji. Rozwiązaniem, które wybrałem, jest użycie środowiska uruchomieniowego Objective-C, aby bezpośrednio pobrać implementację i wywołać ją. Daj mi znać, jeśli ktoś ma lepsze rozwiązanie.Innym problemem jest to, że
navigationBar(_:shouldPop:)
najpierw wywoływana jest następującapopViewController(animated:)
po dotknięciu przycisku Wstecz. Kolejność jest odwracana, jeśli kontroler widoku jest otwierany przez wywołaniepopViewController(animated:)
. W tym przypadku używam wartości logicznej, aby wykryć, czypopViewController(animated:)
została wywołana przed,navigationBar(_:shouldPop:)
co oznacza, że użytkownik nacisnął przycisk Wstecz.Robię również rozszerzenie,
UIViewController
aby umożliwić kontrolerowi nawigacji pytanie kontrolera widoku, czy należy go otworzyć, jeśli użytkownik naciśnie przycisk Wstecz. Kontrolery widoku mogą wrócićfalse
i wykonać niezbędne czynności, apopViewController(animated:)
później zadzwonić .A widząc kontrolery, implementuj
shouldBePopped(_:)
. Jeśli nie zaimplementujesz tej metody, domyślnym zachowaniem będzie wyskakiwanie kontrolera widoku, gdy tylko użytkownik naciśnie przycisk Wstecz, tak jak zwykle.Możesz obejrzeć moje demo tutaj .
źródło
Komunikat „PRZED usunięciem widoku ze stosu”:
źródło
Jest bardziej odpowiedni sposób niż zapytanie ViewControllers. Możesz ustawić swój kontroler jako delegata paska nawigacji, który ma przycisk Wstecz. Oto przykład. W implementacji kontrolera, w którym chcesz obsłużyć naciśnięcie przycisku wstecz, powiedz mu, że zaimplementuje protokół UINavigationBarDelegate:
Następnie gdzieś w kodzie inicjalizacyjnym (prawdopodobnie w viewDidLoad) ustaw kontroler jako delegata paska nawigacji:
Na koniec zaimplementuj metodę shouldPopItem. Ta metoda jest wywoływana zaraz po naciśnięciu przycisku Wstecz. Jeśli masz wiele kontrolerów lub elementów nawigacyjnych w stosie, prawdopodobnie będziesz chciał sprawdzić, które z tych elementów nawigacyjnych są wyskakujące (parametr elementu), abyś robił swoje niestandardowe rzeczy tylko wtedy, gdy się tego spodziewasz. Oto przykład:
źródło
Jeśli nie możesz użyć metody „viewWillDisappear” lub podobnej, spróbuj utworzyć podklasę UINavigationController. To jest klasa nagłówka:
Klasa realizacji:
Z drugiej strony musisz połączyć ten viewController ze swoim niestandardowym NavigationController, więc w swojej metodzie viewDidLoad dla zwykłego viewController wykonaj następujące czynności:
źródło
Oto inny sposób, który zaimplementowałem (nie testowałem go z rozwijaniem płynności, ale prawdopodobnie nie będzie się różnicował, jak stwierdzili inni w odniesieniu do innych rozwiązań na tej stronie), aby nadrzędny kontroler widoku wykonywał akcje przed podrzędnym VC, które wypchnął zostaje wyskakujący ze stosu widoków (użyłem tego kilka poziomów w dół od oryginalnego UINavigationController). Można tego również użyć do wykonywania akcji, zanim childVC zostanie wypchnięte. Ma to dodatkową zaletę w postaci pracy z przyciskiem Wstecz systemu iOS, zamiast konieczności tworzenia niestandardowego UIBarButtonItem lub UIButton.
Poproś swojego rodzica VC o przyjęcie
UINavigationControllerDelegate
protokołu i zarejestrowanie się na wiadomości delegatów:Zaimplementuj tę
UINavigationControllerDelegate
metodę instancji wMyParentViewController
:Jeśli określisz konkretną funkcję zwrotną w powyższej
UINavigationControllerDelegate
metodzie wystąpienia}
źródło
Oto, co działa u mnie w Swift:
źródło
Jeśli używasz Storyboard i pochodzisz z segue push, możesz również po prostu zastąpić
shouldPerformSegueWithIdentifier:sender:
.źródło