Właśnie zacząłem używać Xcode 4.5 i dostałem ten błąd w konsoli:
Ostrzeżenie: Próba zaprezentowania <finishViewController: 0x1e56e0a0> na <ViewController: 0x1ec3e000>, którego widoku nie ma w hierarchii okien!
Widok jest nadal prezentowany i wszystko w aplikacji działa dobrze. Czy to coś nowego w iOS 6?
Oto kod, którego używam do zmiany między widokami:
UIStoryboard *storyboard = self.storyboard;
finishViewController *finished =
[storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];
[self presentViewController:finished animated:NO completion:NULL];
presentViewController:animated:completion
się z kontrolerem nawigacyjnym. Czy robisz to w delegacie aplikacji?Odpowiedzi:
Skąd wywołujesz tę metodę? Wystąpił problem
viewDidLoad
polegający na tym, że próbowałem przedstawić kontroler widoku modalnego w ramach metody. Rozwiązaniem było przeniesienie tego wywołania naviewDidAppear:
metodę.Zakładam, że widok kontrolera widoku nie znajduje się w hierarchii widoku okna w miejscu, w którym został załadowany (kiedy
viewDidLoad
wiadomość jest wysyłana), ale znajduje się w hierarchii okna po jej przedstawieniu (kiedyviewDidAppear:
wiadomość jest wysyłana) .Uwaga
Jeśli nie nawiązać połączenie
presentViewController:animated:completion:
wviewDidAppear:
może napotkasz problem przy czym modalne kontroler widoku jest zawsze przedstawiony ilekroć pojawia się widok kontrolera widoku (która ma sens!) I tak modalna kontroler widoku prezentowane nigdy nie odejdzie .. .Być może nie jest to najlepsze miejsce do prezentacji modalnego kontrolera widoku, a może konieczne jest zachowanie dodatkowego stanu, który pozwala prezentującemu kontrolerowi widoku zdecydować, czy powinien natychmiast przedstawić modalny kontroler widoku.
źródło
Inna potencjalna przyczyna:
Miałem ten problem, gdy przypadkowo dwukrotnie prezentowałem ten sam kontroler widoku. (Raz
performSegueWithIdentifer:sender:
wywołano go po naciśnięciu przycisku, a drugi raz z segue podłączonym bezpośrednio do przycisku).Skutecznie dwa segu strzelały jednocześnie i dostałem błąd:
Attempt to present X on Y whose view is not in the window hierarchy!
źródło
present(viewController, animated: true, completion: nil)
w pętli.viewWillLayoutSubviews
iviewDidLayoutSubviews
(iOS 5.0+) można w tym celu wykorzystać. Są wywoływane wcześniej niż viewDidAppear.źródło
Aby wyświetlić dowolny widok podrzędny do widoku głównego, użyj następującego kodu
Aby odrzucić widok podrzędny z widoku głównego, użyj następującego kodu
źródło
Napotkałem również ten problem, gdy próbowałem przedstawić
UIViewController
wviewDidLoad
. Odpowiedź Jamesa Bedforda zadziałała, ale moja aplikacja najpierw pokazywała tło przez 1 lub 2 sekundy.Po kilku badaniach znalazłem sposób na rozwiązanie tego za pomocą
addChildViewController
.źródło
Prawdopodobnie, podobnie jak ja, masz zły korzeń
viewController
Chcę wyświetlić
ViewController
wnon-UIViewController
kontekście,Więc nie mogę użyć takiego kodu:
Tak więc otrzymuję UIViewController:
Z jakiegoś powodu (błąd logiczny)
rootViewController
jest to coś innego niż oczekiwano (normalneUIViewController
). Następnie naprawiam błąd, zastępującrootViewController
goUINavigationController
, i problem zniknął.źródło
TL; DR Możesz mieć tylko 1 rootViewController i jego najnowszą prezentację. Nie próbuj więc wyświetlać innego kontrolera widoku, gdy jest już przedstawiony kontroler, który nie został zwolniony.
Po przeprowadzeniu kilku własnych testów doszedłem do wniosku.
Jeśli masz rootViewController, który chcesz zaprezentować wszystko, możesz napotkać ten problem.
Oto mój kod rootController (otwarty jest mój skrót do prezentacji kontrolera widoku z katalogu głównego).
Jeśli wywołam open dwa razy z rzędu (niezależnie od upływu czasu), zadziała to dobrze przy pierwszym otwarciu, ale NIE przy drugim otwarciu. Druga otwarta próba spowoduje błąd powyżej.
Jeśli jednak zamknę ostatnio prezentowany widok, a następnie zadzwonię, otwórz, to zadziała dobrze, gdy ponownie wywołam open (na innym kontrolerze widoku).
Doszedłem do wniosku, że rootViewController tylko MOST-RECENT-CALL jest w widoku Hierarchia (nawet jeśli go nie odrzuciłeś ani nie usunąłeś). Próbowałem grać ze wszystkimi wywołaniami modułu ładującego (viewDidLoad, viewDidAppear i wykonywanie opóźnionych wywołań wysyłki) i odkryłem, że jedynym sposobem, w jaki mogę go uruchomić, jest WYŁĄCZNIE wywołanie obecne z najwyżej kontrolera widoku.
źródło
wait
wait
decide
push screen to front
i NIEMOŻLIWE jest IOS ????Mój problem polegał na tym, że przeprowadzałem metodę segue in
UIApplicationDelegate
,didFinishLaunchingWithOptions
zanim zadzwoniłemmakeKeyAndVisible()
do okna.źródło
W mojej sytuacji nie byłem w stanie postawić mojego w zastępstwie klasowym. Oto co mam:
źródło
Miałem ten sam problem. Musiałem osadzić kontroler nawigacyjny i przedstawić go za jego pośrednictwem. Poniżej znajduje się przykładowy kod.
źródło
Jeśli masz obiekt AVPlayer z odtwarzanym wideo, musisz najpierw zatrzymać wideo.
źródło
Miałem ten sam problem. Problem polegał na tym, że performSegueWithIdentifier został wywołany przez powiadomienie, gdy tylko umieściłem powiadomienie w głównym wątku, komunikat ostrzegawczy zniknął.
źródło
Działa dobrze, spróbuj tego. Połączyć
źródło
Na wypadek, gdyby komukolwiek to pomogło, mój problem był wyjątkowo głupi. Oczywiście moja wina. Powiadomienie wyzwalało metodę wywołującą modal. Ale nie usunąłem powiadomienia poprawnie, więc w pewnym momencie miałem więcej niż jedno powiadomienie, więc modal byłby wywoływany wiele razy. Oczywiście po jednorazowym wywołaniu modalu kontroler widoku, który go nazywa, nie znajduje się już w hierarchii widoków, dlatego widzimy ten problem. Moja sytuacja spowodowała także wiele innych problemów, jak można się spodziewać.
Podsumowując, cokolwiek robisz, upewnij się, że modal nie zostanie wywołany więcej niż raz .
źródło
Skończyło się na takim kodzie, który w końcu działa dla mnie (Swift), biorąc pod uwagę, że chcesz wyświetlić niektóre
viewController
z dowolnego miejsca. Ten kod oczywiście zawiesi się, gdy nie będzie dostępny rootViewController, to jest otwarte zakończenie. Nie obejmuje również zwykle wymaganego przejścia na wątek interfejsu użytkownika za pomocąźródło
Ten rodzaj ostrzeżenia może oznaczać, że próbujesz obecnego nowego
View Controller
throughNavigation Controller
podczas gdy tenNavigation Controller
jest obecnie prezentuje innyView Controller
. Aby to naprawić, musiszView Controller
najpierw odrzucić prezentację, a po jej zakończeniu przedstawić nową. Inną przyczyną ostrzeżenia może być próba przedstawieniaView Controller
w wątku innej niżmain
.źródło
Naprawiłem to, przenosząc
start()
funkcję dodismiss
bloku uzupełniania:Start zawiera dwa połączenia z
self.present()
jednym dla UINavigationController i drugim dlaUIImagePickerController
.To naprawiło to dla mnie.
źródło
Miałem podobny problem na Swift 4.2, ale mój widok nie był prezentowany z cyklu widoków. Przekonałem się, że miałem wiele segmentów do zaprezentowania w tym samym czasie. Więc użyłem dispatchAsyncAfter.
źródło
Możesz również otrzymać to ostrzeżenie podczas wykonywania segue z kontrolera widoku, który jest osadzony w kontenerze. Prawidłowym rozwiązaniem jest użycie segue od rodzica kontenera, a nie od kontrolera widoku kontenera.
źródło
Muszę napisać poniżej linii.
zamiast
w UIViewController
źródło
Z Swift 3 ...
Inną możliwą przyczyną tego, co mi się przydarzyło, było przechodzenie od tableViewCell do innego ViewController na Storyboard. Użyłem również,
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {}
gdy komórka została kliknięta.Rozwiązałem ten problem, tworząc segment z ViewController do ViewController.
źródło
Miałem ten problem, a główną przyczyną było wielokrotne subskrybowanie modułu obsługi kliknięć przycisków (TouchUpInside).
Subskrybował w ViewWillAppear, który był wywoływany wiele razy, ponieważ dodaliśmy nawigację, aby przejść do innego kontrolera, a następnie zrelaksować się z powrotem.
źródło
Zdarzyło mi się, że segue w serii ujęć był zepsuty . Usunięcie segue (i ponowne utworzenie dokładnie tego samego segregacji) rozwiązało problem.
źródło
W głównym oknie prawdopodobnie zawsze będą czasy z przejściami, które są niezgodne z wyświetlaniem alertu. Aby umożliwić prezentowanie alertów w dowolnym momencie cyklu życia aplikacji, powinieneś mieć osobne okno do wykonania zadania.
Podstawowe użycie, które z założenia zawsze będzie skuteczne:
źródło
Niestety przyjęte rozwiązanie nie zadziałało w moim przypadku. Próbowałem przejść do nowego kontrolera widoku zaraz po odprężeniu z innego kontrolera widoku.
Znalazłem rozwiązanie, używając flagi, aby wskazać, który wywoływano segue odwijania.
Następnie zaprezentuj poszukiwany VC
present(_ viewControllerToPresent: UIViewController)
Zasadniczo powyższy kod pozwoli mi złapać odprężenie przy logowaniu / SignUp VC i przejść do deski rozdzielczej lub złapać akcję odprężania od zapomnienia hasła VC i przejść do strony logowania.
źródło
Naprawiłem ten błąd polegający na zapisywaniu najwyższego kontrolera widoku w stałą, który można znaleźć w trakcie cyklu nad rootViewController:
źródło
Znalazłem ten błąd, który pojawił się po aktualizacji Xcode, wierzę w Swift 5 . Problem pojawił się, gdy programowo uruchomiłem segue bezpośrednio po rozwinięciu kontrolera widoku.
Rozwiązanie pojawiło się podczas naprawy powiązanego błędu, który polegał na tym, że użytkownik mógł teraz odwijać segu, przesuwając stronę w dół. To złamało logikę mojego programu.
Zostało to naprawione poprzez zmianę trybu prezentacji na wszystkich kontrolerach widoku z Automatycznego na Pełny ekran .
Możesz to zrobić w panelu atrybutów w kreatorze interfejsów. Lub zobacz tę odpowiedź, aby dowiedzieć się, jak to zrobić programowo.
źródło
Właśnie miałem ten problem, ale nie miało to nic wspólnego z czasem. Użyłem singletona do obsługi scen i ustawiłem go jako prezentera. Innymi słowy „jaźń” nie była do niczego podłączona. Właśnie stworzyłem jej „scenę” nowym prezenterem i voila, zadziałało. (Voila traci kontakt, gdy nauczysz się jego znaczenia, heh).
Więc tak, nie chodzi o „magiczne znalezienie właściwej drogi”, ale o zrozumienie, gdzie stoi twój kod i co robi. Cieszę się, że Apple dał tak jednoznacznie angielski komunikat ostrzegawczy, nawet z emocjami. Uznanie dla twórcy jabłek, który to zrobił !!
źródło
Jeśli z jakiegoś powodu inne rozwiązania nie wyglądają dobrze, nadal możesz użyć tego starego dobrego
workaround
prezentowania z opóźnieniem 0, na przykład:Chociaż nie widziałem żadnej udokumentowanej gwarancji, że Twój VC będzie w hierarchii widoków w bloku wysłania czasu, który jest zaplanowany do wykonania, zauważyłem, że będzie dobrze.
Opcjonalne jest również użycie opóźnienia wynoszącego np. 0,2 sekundy. I najlepsza rzecz - w ten sposób nie musisz zadzierać ze zmienną logiczną
viewDidAppear:
źródło
Działa to w celu przedstawienia dowolnego kontrolera widoku, jeśli masz dostępny kontroler nawigacji. self.navigationController? .present (MyViewController, animowany: true, ukończenie: zero) Ponadto mogę również przedstawiać alerty i kontroler poczty.
źródło