Czytałem wiele postów na temat osób mających problemy z viewWillAppear
, jeśli nie utworzyć widok hierarchii tuż tuż. Mój problem polega na tym, że nie mogę zrozumieć, co to znaczy.
Jeśli utworzę RootViewController
i wywołam addSubView
ten kontroler, spodziewałbym się, że dodane widoki będą okablowane dla viewWillAppear
zdarzeń.
Czy ktoś ma przykład złożonej hierarchii widoków programistycznych, która z powodzeniem odbiera viewWillAppear
zdarzenia na każdym poziomie?
Stan Dokumentów Apple:
Ostrzeżenie: jeśli widok należący do kontrolera widoku zostanie dodany bezpośrednio do hierarchii widoków, kontroler widoku nie otrzyma tego komunikatu. Jeśli wstawisz lub dodasz widok do hierarchii widoków i ma on kontroler widoku, powinieneś wysłać tę wiadomość bezpośrednio do skojarzonego kontrolera widoku. Jeśli nie wyślesz kontrolera widoku, ta wiadomość uniemożliwi wyświetlenie skojarzonej animacji.
Problem w tym, że nie opisują, jak to zrobić. Co oznacza „bezpośrednio”? Jak „pośrednio” dodajesz widok?
Jestem całkiem nowy w Cocoa i iPhonie, więc byłoby miło, gdyby oprócz podstawowego bzdura z Hello World były przydatne przykłady od Apple.
źródło
Odpowiedzi:
Jeśli używasz kontrolera nawigacji i ustawisz jego delegata, metody widoku {Will, Did} {Appear, Disappear} nie zostaną wywołane.
Zamiast tego należy użyć metod delegata kontrolera nawigacji:
źródło
Napotkałem ten sam problem. Po prostu wyślij
viewWillAppear
wiadomość do kontrolera widoku, zanim dodasz go jako widok podrzędny. (Jest jeden parametr BOOL, który informuje kontroler widoku, czy animacja ma się pojawić, czy nie).Spójrz na RootViewController.m w przykładzie metronomu.
(Właściwie uważam, że przykładowe projekty Apple'a są świetne. Jest o wiele więcej niż HelloWorld;)
źródło
[scrollView addSubview:controller.view];
.[controller viewWillAppear:NO];
Później dodałem linię i voila! Działał jak urok.W końcu znalazłem rozwiązanie, które DZIAŁA!
UINavigationControllerDelegate
Myślę, że sednem tego jest ustawienie delegata kontrolki nawigacji na kontroler widoku, w którym się znajduje, i zaimplementowanie
UINavigationControllerDelegate
dwóch metod. Znakomity! Jestem tak podekscytowany, że w końcu znalazłem rozwiązanie!źródło
Po prostu miałem ten sam problem. W mojej aplikacji mam 2 kontrolery nawigacyjne i wciskanie tego samego kontrolera widoku w każdym z nich działało w jednym przypadku a nie w drugim. Chodzi mi o to, że po naciśnięciu tego samego kontrolera widoku w pierwszym
UINavigationController
,viewWillAppear
został wywołany, ale nie po naciśnięciu drugiego kontrolera nawigacyjnego.Potem natknąłem się na ten post UINavigationController powinien wywołać metody viewWillAppear / viewWillDisappear
I zdałem sobie sprawę, że mój drugi kontroler nawigacyjny przedefiniował
viewWillAppear
. Sprawdzanie kodu pokazało, że nie dzwonięDodałem i zadziałało!
Dokumentacja mówi:
źródło
Używałem kontrolera nawigacyjnego. Kiedy chcę zejść do innego poziomu danych lub pokazać mój widok niestandardowy, używam następujących opcji:
Kiedy to robię,
viewWillAppear
funkcja uruchamia się. Przypuszczam, że to kwalifikuje się jako „pośrednie”, ponieważ sam nie wywołuję właściwejaddSubView
metody. Nie wiem, czy ma to zastosowanie w 100% do Twojej aplikacji, ponieważ nie mogę stwierdzić, czy używasz kontrolera nawigacyjnego, ale może to da wskazówkę.źródło
Dzięki iOS 13.
Kredyty idą do Arka Holko . Naprawdę uratował mi dzień.
źródło
Po pierwsze, pasek zakładek powinien znajdować się na poziomie głównym, tj. Być dodany do okna, zgodnie z dokumentacją Apple. Ma to kluczowe znaczenie dla prawidłowego zachowania.
Po drugie, można użyć
UITabBarDelegate
/UINavigationBarDelegate
do przekazania powiadomień ręcznie, ale okazało się, że aby dostać całą hierarchię widzenia połączeń działała poprawnie, wszystko, co musiałem zrobić, to połączenie ręczniei
.. TYLKO RAZ przed skonfigurowaniem kontrolerów widoku na odpowiednim kontrolerze (zaraz po przypisaniu). Odtąd poprawnie wywoływał te metody na swoich kontrolerach widoku podrzędnego.
Moja hierarchia wygląda tak:
Już samo wywołanie wspomnianych metod na kontrolerze tab / nav po raz pierwszy zapewniło poprawne przekazanie WSZYSTKICH zdarzeń. Powstrzymało mnie to od ręcznego dzwonienia do nich z
UINavigationBarDelegate
/UITabBarControllerDelegate
Methods.Uwaga dodatkowa: Co ciekawe, kiedy to nie działało, metoda prywatna
.. który możesz zobaczyć ze stosu wywołań na działającej implementacji, zwykle wywołuje
viewWill/Did..
metody, ale tak się nie dzieje, dopóki nie wykonałem powyższego (mimo że został wywołany).Myślę, że BARDZO ważne jest, aby plik
UITabBarController
był na poziomie okna, a dokumenty wydają się to potwierdzać.Mam nadzieję, że to było jasne (ish), chętnie odpowiem na dalsze pytania.
źródło
Ponieważ żadna odpowiedź nie jest akceptowana, a ludzie (tak jak ja) lądują tutaj, podaję moją odmianę. Chociaż nie jestem pewien, czy to był pierwotny problem. Kiedy kontroler nawigacji jest dodawany jako podwidok do innego widoku, musisz sam wywołać metody viewWillAppear / Dissappear itp. W następujący sposób:
Żeby przykład był kompletny. Ten kod pojawia się w moim ViewController, w którym utworzyłem i dodałem kontroler nawigacji do widoku, który umieściłem w widoku.
.h wygląda tak
W pliku nib mam widok, a poniżej tego widoku mam etykietę obraz i kontener (inny widok), w którym umieszczam kontroler. Oto jak to wygląda. Musiałem wymieszać kilka rzeczy, ponieważ to była praca dla klienta.
źródło
Widoki są dodawane „bezpośrednio”, dzwoniąc
[view addSubview:subview]
. Widoki są dodawane „pośrednio” za pomocą takich metod, jak paski kart lub paski nawigacji, które zamieniają widoki podrzędne.Za każdym razem, gdy dzwonisz
[view addSubview:subviewController.view]
, powinieneś zadzwonić[subviewController viewWillAppear:NO]
(lub TAK, w zależności od przypadku).Miałem ten problem, kiedy zaimplementowałem własny system zarządzania widokiem roota dla podekranu w grze. Ręczne dodanie wywołania do viewWillAppear wyleczyło mój problem.
źródło
Poprawnym sposobem na to jest użycie interfejsu API zawierającego UIViewController.
źródło
viewWillAppear:
nadal nie można nazwaćUżywam tego kodu dla kontrolerów widoku push i pop:
Pchać:
Muzyka pop:
.. i dla mnie działa dobrze.
źródło
Bardzo częsty błąd jest następujący. Masz jeden widok,
UIView* a
i jeszcze jeden,UIView* b
. Dodajesz b do a jako widok podrzędny. Jeśli spróbujesz wywołać viewWillAppear w b, to nigdy nie zostanie on uruchomiony, ponieważ jest to podwidokźródło
iOS 13 wbił moją aplikację w tyłek tutaj. Jeśli zauważyłeś zmianę w zachowaniu od iOS 13, po prostu ustaw następujące ustawienia przed wysłaniem:
Konieczne może być również ustawienie go w .storyboard w Inspektorze atrybutów (ustaw prezentację na pełny ekran).
Dzięki temu Twoja aplikacja będzie działać tak, jak we wcześniejszych wersjach systemu iOS.
źródło
Nie jestem tego w 100% pewien, ale myślę, że dodanie widoku do hierarchii widoków bezpośrednio oznacza wywołanie
-addSubview:
widoku kontrolera widoku (np.[viewController.view addSubview:anotherViewController.view]
) Zamiast wypychania nowego kontrolera widoku na stos kontrolera nawigacji.źródło
Myślę, że dodanie widoku podrzędnego niekoniecznie oznacza, że widok się pojawi, więc nie ma automatycznego wywołania metody klasy, która będzie
źródło
Myślę, że to, co mają na myśli „bezpośrednio”, to podłączanie rzeczy w taki sam sposób, jak robi to szablon xcode „Navigation Application”, który ustawia UINavigationController jako jedyny podwidok okna UIWindow aplikacji.
Korzystanie z tego szablonu jest jedynym sposobem, w jaki mogłem uzyskać metody Will / Did / Appear / Disappear wywoływane w obiekcie ViewControllers po wypychaniu / wyskakiwaniu tych kontrolerów w UINavigationController. Żadne z innych rozwiązań w odpowiedziach tutaj nie zadziałało, w tym wdrożenie ich w RootController i przekazanie ich do (podrzędnego) NavigationController. Te funkcje (będą / pojawiały się / znikały) były wywoływane w moim RootController dopiero po wyświetleniu / ukryciu VC najwyższego poziomu, moich "loginów" i nawigacji VC, a nie sub-VC w kontrolerze nawigacji, więc nie miałem możliwości „przepuść je” do Nav VC.
Skończyło się na tym, że skorzystałem z funkcji delegata UINavigationControllera, aby wyszukać konkretne przejścia, które wymagały dalszych funkcji w mojej aplikacji, i to działa, ale wymaga trochę więcej pracy, aby „zasymulować” zniknięcie i pojawienie się funkcjonalności.
Również z zasady jest sprawą, aby zadziałał po tym, jak godzinami walę się dziś głową w ten problem. Wszelkie działające fragmenty kodu korzystające z niestandardowego RootController i podrzędnego VC nawigacji byłyby bardzo mile widziane.
źródło
Na wypadek, gdyby to komuś pomogło. Miałem podobny problem, gdy mój
ViewWillAppear
nie odpala naUITableViewController
. Po wielu zabawach zdałem sobie sprawę, że problem polegał na tym,UINavigationController
że to, co kontroluje,UITableView
nie jest w widoku głównym. Kiedy to naprawię, teraz działa jak mistrz.źródło
Po prostu miałem ten problem i zajęło mi to 3 pełne godziny (z czego 2 googlowanie), aby go naprawić.
Pomocne okazało się po prostu usunięcie aplikacji z urządzenia / symulatora, wyczyszczenie i ponowne uruchomienie .
Mam nadzieję, że to pomoże
źródło
Ustaw delegata na główny kontroler widoku.
źródło
Dla Swift. Najpierw utwórz protokół, aby wywołać to, co chcesz wywołać w viewWillAppear
Po drugie, utwórz klasę
}
Po trzecie, ustaw wystąpienie ForceUpdateOnViewAppear jako element członkowski odpowiedniej klasy, która ma dostęp do kontrolera nawigacji i istnieje tak długo, jak istnieje kontroler nawigacji. Może to być na przykład główny kontroler widoku kontrolera nawigacji lub klasa, która go tworzy lub przedstawia. Następnie przypisz wystąpienie ForceUpdateOnViewAppear do właściwości delegata kontrolera nawigacji tak wcześnie, jak to możliwe.
źródło
W moim przypadku problem był z niestandardową animacją przejścia. Po ustawieniu
modalPresentationStyle = .custom
viewWillAppear
nie wywołanew niestandardowej klasie animacji przejścia potrzebne są metody wywołania:
beginAppearanceTransition
iendAppearanceTransition
źródło
W moim przypadku był to po prostu dziwny błąd w emulatorze iOS 12.1. Zniknął po uruchomieniu na prawdziwym urządzeniu.
źródło
Stworzyłem klasę, która rozwiązuje ten problem. Po prostu ustaw go jako delegata kontrolera nawigacji i zaimplementuj prostą jedną lub dwie metody w kontrolerze widoku - które zostaną wywołane, gdy widok ma zostać wyświetlony lub został wyświetlony za pośrednictwem NavigationController
Oto GIST pokazujący kod
źródło
ViewWillAppear jest metodą nadpisywania klasy UIViewController, więc dodanie subView nie wywoła metody viewWillAppear, ale podczas prezentacji, push, pop, show, setFront lub popToRootViewController z elementu viewController zostanie wywołane viewWillAppear dla prezentowanego elementu viewController.
źródło
Mój problem polegał na tym, że viewWillAppear nie był wywoływany podczas wychodzenia z kolejki. Odpowiedzią było wywołanie viewWillAppear (true) w rozwiniętym segue w kontrolerze widoku, do którego wracasz
@IBAction func unind (for relaxSegue: UIStoryboardSegue, ViewController FurtherVC: Any) {
źródło
Nie jestem pewien, czy to ten sam problem, który rozwiązałem.
W niektórych przypadkach metoda nie jest wykonywana w normalny sposób, na przykład „[self methodOne]”.
Próbować
źródło
viewWillAppear
nie jest w ogóle wywołanyW dowolnym momencie powinien być aktywny tylko 1 kontroler UIViewController. Wszelkie podziały, którymi chcesz manipulować, powinny być dokładnie takie - subVIEWS - czyli UIView.
Używam prostej techniki do zarządzania moją hierarchią widoków i nie napotkałem jeszcze problemu, odkąd zacząłem robić rzeczy w ten sposób. Istnieją 2 kluczowe punkty:
Co rozumiem przez „wartość ekranu”? Celowo jest trochę niejasny, ale generalnie jest to funkcja lub sekcja Twojej aplikacji. Jeśli masz kilka ekranów z tym samym obrazem tła, ale różnymi nakładkami / wyskakującymi okienkami itp., Powinien to być 1 kontroler widoku i kilka widoków podrzędnych. Nigdy nie powinieneś pracować z dwoma kontrolerami widoku. Należy zauważyć, że nadal można utworzyć wystąpienie UIView w jednym kontrolerze widoku i dodać go jako widok podrzędny innego kontrolera widoku, jeśli chcesz, aby określone obszary ekranu były wyświetlane w wielu kontrolerach widoku.
Jeśli chodzi o UINavigationController - to twój najlepszy przyjaciel! Wyłącz pasek nawigacji i określ NIE dla animacji, a będziesz mieć doskonały sposób przełączania ekranów na żądanie. Możesz wypchnąć i wyskoczyć kontrolery widoku, jeśli są w hierarchii, lub możesz przygotować tablicę kontrolerów widoku (w tym tablicę zawierającą pojedynczy VC) i ustawić ją jako stos widoku przy użyciu setViewControllers. Daje to całkowitą swobodę zmiany VC, jednocześnie zyskując wszystkie zalety pracy w oczekiwanym modelu Apple i poprawnego uruchamiania wszystkich wydarzeń itp.
Oto, co robię za każdym razem, gdy uruchamiam aplikację:
(uwaga zaczynająca się od okna to tylko osobiste preferencje - lubię konstruować rzeczy samodzielnie, więc wiem dokładnie, jak są budowane. Powinno działać dobrze z szablonem opartym na widoku)
Wszystkie zdarzenia strzelają poprawnie i w zasadzie życie jest dobre. Następnie możesz poświęcić cały swój czas na pisanie ważnych fragmentów aplikacji i nie martwić się próbami ręcznego zhakowania hierarchii widoków do kształtu.
źródło