Próbuję zastąpić domyślną akcję przycisku Wstecz w kontrolerze nawigacyjnym. Podałem celowi akcję na przycisku niestandardowym. Dziwne jest to, że przypisując go za pomocą atrybutu backbutton, nie zwraca na nie uwagi, po prostu wyskakuje bieżący widok i wraca do katalogu głównego:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle: @"Servers"
style:UIBarButtonItemStylePlain
target:self
action:@selector(home)];
self.navigationItem.backBarButtonItem = backButton;
Tak szybko, jak ustawić go poprzez leftBarButtonItem
na navigationItem
nim moje działanie wywołuje jednak następnie przycisk wygląda jak zwykły rundzie zamiast z powrotem jedną strzałką:
self.navigationItem.leftBarButtonItem = backButton;
Jak mogę wywołać moją niestandardową akcję przed powrotem do widoku głównego? Czy istnieje sposób na zastąpienie domyślnej akcji cofania, czy też istnieje metoda, która jest zawsze wywoływana przy opuszczaniu widoku ( viewDidUnload
nie robi tego)?
Odpowiedzi:
Spróbuj umieścić to w kontrolerze widoku, w którym chcesz wykryć prasę:
źródło
if (find(self.navigationController!.viewControllers as! [UIViewController],self)==nil)
I zostały wdrożone UIViewController-BackButtonHandler rozszerzenie. Nie trzeba go podklasować, wystarczy umieścić go w projekcie i zastąpić
navigationShouldPopOnBackButton
metodę wUIViewController
klasie:Pobierz przykładową aplikację .
źródło
navigationBar:shouldPopItem:
nie jest prywatna metoda, ponieważ jest częściąUINavigationBarDelegate
protokołu.YES
)? czy będzie w przyszłości? podklasowanie jest prawdopodobnie bezpieczniejszą opcjąNO
przycisk Wstecz pozostaje w stanie wyłączonym (wizualnie, ponieważ nadal odbiera i reaguje na zdarzenia dotykowe). Obejrzałem go, dodającelse
oświadczenie doshouldPop
kontroli i przechodząc między widokami paska nawigacji i ustawiającalpha
wartość z powrotem na 1, jeśli to konieczne, w bloku animacji: gist.github.com/idevsoftware/9754057W przeciwieństwie do tego, co powiedział Amagrammer, jest to możliwe. Musisz podklasować swój
navigationController
. Wyjaśniłem wszystko tutaj (w tym przykładowy kod).źródło
Wersja szybka:
(z https://stackoverflow.com/a/19132881/826435 )
W kontrolerze widoku wystarczy dostosować protokół i wykonać dowolne czynności:
Następnie utwórz klasę, powiedzmy
NavigationController+BackButton
, i po prostu skopiuj i wklej poniższy kod:źródło
shouldPopOnBackButtonPress
powinien zostać wywołany, dopóki nie będzie żadnych błędów.performSomeActionOnThePressOfABackButton
jest tylko wymyśloną metodą, która nie istnieje.performSomeActionOnThePressOfABackButton
w kontrolerze metodę wykonywania określonej akcji po naciśnięciu przycisku Wstecz, ale ta metoda nigdy nie została wywołana, akcja jest normalnym powrotem wsteczUINavigationController
,navigationBar.delegate
jest ustawiony na kontroler nawigacyjny. Tak więc metody POWINNY zostać wywołane. Jednak w Swift nie mogę ich wezwać, nawet w podklasie. Udało mi się jednak wywołać je w Objective-C, więc na razie użyję wersji Objective-C. Może to być szybki błąd.Nie można tego zrobić bezpośrednio. Istnieje kilka alternatyw:
UIBarButtonItem
który będzie sprawdzany po naciśnięciu i wyskakuje, jeśli test się powiedzieUITextField
metody delegowania, takiej jak-textFieldShouldReturn:
, która jest wywoływana po naciśnięciu przyciskuReturn
lubDone
na klawiaturzeMinusem pierwszej opcji jest to, że nie można uzyskać dostępu do stylu strzałki w lewo przycisku Wstecz za pomocą niestandardowego przycisku paska. Musisz więc użyć obrazu lub użyć zwykłego przycisku stylu.
Druga opcja jest przydatna, ponieważ pole tekstowe dostajesz z powrotem w metodzie delegowania, dzięki czemu możesz kierować logikę sprawdzania poprawności do określonego pola tekstowego wysłanego do metody oddzwaniania delegata.
źródło
Z kilku powodów wątków rozwiązanie wspomniane przez @HansPinckaers nie było dla mnie odpowiednie, ale znalazłem łatwiejszy sposób, aby dotknąć przycisku Wstecz, i chcę to tutaj przypiąć, aby uniknąć godzin oszustwa ktoś inny. Sztuczka jest naprawdę łatwa: wystarczy dodać przezroczysty UIButton jako widok podrzędny do paska UINavigation i ustawić dla niego selektory tak, jakby to był prawdziwy przycisk! Oto przykład użycia Monotouch i C #, ale tłumaczenie na cel-c nie powinno być trudne do znalezienia.
Ciekawostka: dla celów testowych i znalezienia dobrych wymiarów mojego fałszywego przycisku ustawiłem kolor tła na niebieski ... I pokazuje się za przyciskiem Wstecz! W każdym razie nadal łapie dotyk dotykający oryginalnego przycisku.
źródło
Ta technika umożliwia zmianę tekstu przycisku „wstecz” bez wpływu na tytuł dowolnego kontrolera widoku lub zmianę tekstu przycisku wstecz podczas animacji.
Dodaj to do metody init w wywołującym kontrolerze widoku:
źródło
Najprostszy sposób
Możesz użyć metod delegowania UINavigationController. Metoda
willShowViewController
jest wywoływana po naciśnięciu przycisku Wstecz VC. Wykonaj dowolną czynność po naciśnięciu Wstecz btnźródło
Oto moje rozwiązanie Swift. W podklasie klasy UIViewController zastąp metodę nawigacji NavigationShouldPopOnBackButton.
źródło
Znaleziono rozwiązanie, które zachowuje również styl przycisku wstecz. Dodaj następującą metodę do kontrolera widoku.
Teraz zapewnij funkcjonalność zgodnie z potrzebami w następującej metodzie:
Wystarczy zakryć tylny przycisk przezroczystym przyciskiem;)
źródło
========================================
Opierając się na poprzednich odpowiedziach z UIAlert w Swift5 w sposób asynchroniczny
Na twoim kontrolerze
źródło
Nie sądzę, że jest to możliwe, łatwo. Uważam, że jedynym sposobem na obejście tego jest zrobienie własnego obrazu strzałki wstecz. Na początku było to dla mnie frustrujące, ale rozumiem, dlaczego, dla zachowania spójności, zostało to pominięte.
Możesz się zbliżyć (bez strzałki), tworząc zwykły przycisk i ukrywając domyślny przycisk powrotu:
źródło
Jest łatwiejszy sposób tylko przez instacji metodę delegata z poniższych
UINavigationBar
i zastąpić tenShouldPopItem
sposób .źródło
Rozwiązanie onegray nie jest bezpieczne. Według oficjalnych dokumentów Apple, https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html powinniśmy tego unikać.
„Jeśli nazwa metody zadeklarowanej w kategorii jest taka sama jak metoda w oryginalnej klasie lub metoda w innej kategorii w tej samej klasie (lub nawet nadklasie), zachowanie nie jest określone, która implementacja metody jest używana w czasie wykonywania. Mniej prawdopodobne jest, że będzie to problem, jeśli używasz kategorii z własnymi klasami, ale może powodować problemy podczas korzystania z kategorii w celu dodania metod do standardowych klas Cocoa lub Cocoa Touch. ”
źródło
Za pomocą Swift:
źródło
Oto wersja Swift 3 odpowiedzi @oneway na przechwytywanie zdarzenia przycisku wstecz paska nawigacji, zanim zostanie zwolniony. Ponieważ
UINavigationBarDelegate
nie można go użyćUIViewController
, musisz utworzyć delegata, który będzie uruchamiany ponavigationBar
shouldPop
wywołaniu.Następnie w kontrolerze widoku dodaj funkcję delegowania:
Zdałem sobie sprawę, że często chcemy dodać kontroler alertów, aby użytkownicy mogli zdecydować, czy chcą wrócić. Jeśli tak, to można zawsze
return false
wnavigationShouldPopOnBackButton()
funkcji kontrolera i zamknąć widok robiąc coś takiego:źródło
Value of type 'UIViewController' has no member 'navigationShouldPopOnBackButton'
gdy próbuję skompilować kod, na liniiif vc.responds(to: #selector(v...
Ponadtoself.topViewController
zwraca opcjonalny i nie jest ostrzeżeniem dla że również.let vc = self.topViewController as! MyViewController
i wydaje się, że do tej pory działał dobrze. Jeśli uważasz, że to właściwa zmiana, możesz edytować kod. Ponadto, jeśli uważasz, że nie należy tego robić, chętnie dowiem się, dlaczego. Dzięki za ten kod. Prawdopodobnie powinieneś napisać o tym post na blogu, ponieważ ta odpowiedź jest zakopana według głosów.MyViewController
brak zgodnościBackButtonDelegate
. Zamiast wymuszać rozpakowywanie, powinieneś zrobić,guard let vc = self.topViewController as? MyViewController else { return true }
aby uniknąć możliwej awarii.guard let vc = self.topViewController as? MyViewController else { self.popViewController(animated: true) return true }
aby upewnić się, że ekran przesuwa się na właściwą stronę na wypadek, gdyby nie można go poprawnie rzucić. Rozumiem teraz, żenavigationBar
funkcja jest wywoływana we wszystkich VC, a nie tylko w kontroler widoków, w którym ten kod istnieje. Czy może warto też zaktualizować kod w odpowiedzi? Dzięki.Wersja Swift 4 iOS 11.3:
Opiera się to na odpowiedzi od kgaidis z https://stackoverflow.com/a/34343418/4316579
Nie jestem pewien, kiedy rozszerzenie przestało działać, ale w momencie pisania tego tekstu (Swift 4) wydaje się, że rozszerzenie nie będzie już wykonywane, dopóki nie zadeklarujesz zgodności UINavigationBarDelegate, jak opisano poniżej.
Mam nadzieję, że to pomaga ludziom, którzy zastanawiają się, dlaczego ich rozszerzenie już nie działa.
źródło
Używając zmiennych target i action, w których obecnie pozostawiasz „zero”, powinieneś być w stanie połączyć swoje okna dialogowe zapisywania, aby były wywoływane, gdy przycisk jest „wybrany”. Uważaj, może się to uruchomić w dziwnych momentach.
Zgadzam się głównie z Amagrammerem, ale nie sądzę, że byłoby tak trudno stworzyć przycisk z niestandardową strzałką. Chciałbym tylko zmienić nazwę przycisku Wstecz, zrobić zrzut ekranu, Photoshop potrzebnego rozmiaru przycisku i niech to będzie obraz na górze twojego przycisku.
źródło
Możesz spróbować uzyskać dostęp do elementu prawego przycisku nawigacji i ustawić jego właściwość selektora ... oto referencja UIBarButtonItem referencja , kolejna rzecz, jeśli ta najdrobniejsza praca, która będzie działać, to ustawić element prawego przycisku paska nawigacyjnego na niestandardowy UIBarButtonItem, który utwórz i ustaw selektor ... mam nadzieję, że to pomoże
źródło
W przypadku formularza, który wymaga takiego wkładu użytkownika, zaleciłbym wywołanie go jako „modalnego” zamiast części stosu nawigacji. W ten sposób muszą zająć się biznesem na formularzu, a następnie można go zweryfikować i odrzucić za pomocą niestandardowego przycisku. Możesz nawet zaprojektować pasek nawigacyjny, który będzie wyglądał tak samo jak reszta aplikacji, ale da ci większą kontrolę.
źródło
Aby przechwycić przycisk Wstecz, po prostu przykryj go przezroczystym interfejsem UIControl i przechwytuj dotyk.
źródło
Przynajmniej w Xcode 5 istnieje proste i całkiem dobre (nie idealne) rozwiązanie. W IB przeciągnij element przycisku paska z panelu Narzędzia i upuść go po lewej stronie paska nawigacji, gdzie będzie przycisk Wstecz. Ustaw etykietę na „Wstecz”. Będziesz miał działający przycisk, który możesz powiązać z IBAction i zamknąć viewController. Robię trochę pracy, a następnie uruchamiam segregację odprężającą i działa idealnie.
To, co nie jest idealne, to to, że ten przycisk nie otrzymuje strzałki <i nie przenosi poprzedniego tytułu VC, ale myślę, że można to zarządzać. Dla moich celów ustawiłem nowy przycisk Wstecz jako przycisk „Gotowe”, więc jego cel jest jasny.
W nawigatorze IB możesz także skończyć z dwoma przyciskami Wstecz, ale łatwo jest oznaczyć go dla zachowania przejrzystości.
źródło
Szybki
źródło
To podejście zadziałało dla mnie (ale przycisk „Wstecz” nie będzie miał znaku „<”):
źródło
Szybka wersja odpowiedzi @ onegray
Teraz w dowolnym kontrolerze, po prostu dostosuj się,
RequestsNavigationPopVerification
a to zachowanie zostanie przyjęte domyślnie.źródło
Posługiwać się
isMovingFromParentViewController
źródło
viewDidDisappear
. W ten sposób uruchomi się tylko po definitywnym zniknięciu widoku.Odpowiedź od @William jest jednak poprawna, jeśli użytkownik rozpocznie gest przesunięcia do tyłu,
viewWillDisappear
metoda zostanie wywołana i nawetself
nie będzie w stosie nawigacyjnym (to znaczyself.navigationController.viewControllers
nie będzie zawieraćself
), nawet jeśli przesunięcie nie jest ukończony, a kontroler widoku nie jest faktycznie wyskakujący. Zatem rozwiązaniem byłoby:Wyłącz gest przesuwania palcem do tyłu
viewDidAppear
i zezwalaj tylko na użycie przycisku Wstecz, używając:Lub po prostu użyj
viewDidDisappear
zamiast tego w następujący sposób:źródło
Rozwiązanie, które znalazłem do tej pory, nie jest zbyt ładne, ale działa dla mnie. Biorąc tę odpowiedź , sprawdzam również, czy popping programowo, czy nie:
Musisz dodać tę właściwość do kontrolera i ustawić ją na TAK, zanim pojawi się programowo:
źródło
Znalazłem nowy sposób na zrobienie tego:
Cel C
Szybki
źródło