Próbuję przedstawić, ViewController
czy w modelu danych są jakieś zapisane dane. Ale pojawia się następujący błąd:
Ostrzeżenie: próba prezentacji * na *, którego widok nie znajduje się w hierarchii okien "
Odpowiedni kod:
override func viewDidLoad() {
super.viewDidLoad()
loginButton.backgroundColor = UIColor.orangeColor()
var request = NSFetchRequest(entityName: "UserData")
request.returnsObjectsAsFaults = false
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext!
var results:NSArray = context.executeFetchRequest(request, error: nil)!
if(results.count <= 0){
print("Inga resultat")
} else {
print("SWITCH VIEW PLOX")
let internVC = self.storyboard?.instantiateViewControllerWithIdentifier("internVC") as internViewController
self.presentViewController(internVC, animated: true, completion: nil)
}
}
Próbowałem różnych rozwiązań znalezionych przy użyciu Google bez powodzenia.
ios
swift
hierarchy
presentviewcontroller
Nils Wasell
źródło
źródło
ViewController
w Storyboard? Nie używamNavigationController
@derdidaUIViewController
część). @derdidaOdpowiedzi:
W tym momencie w kodzie widok kontrolera widoku został tylko utworzony, ale nie został dodany do żadnej hierarchii widoków. Jeśli chcesz zaprezentować kontroler z tego widoku tak szybko, jak to możliwe, powinieneś to zrobić,
viewDidAppear
aby być najbezpieczniejszym.źródło
W celu c: To rozwiązało mój problem podczas prezentowania kontrolera widoku na mpmovieplayer
- (UIViewController*) topMostController { UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController; while (topController.presentedViewController) { topController = topController.presentedViewController; } return topController; }
źródło
Szybki 3
Miałem to ciągle pojawiać się jako nowicjusz i odkryłem, że obecne ładuje widoki modalne, które można odrzucić, ale przełączenie na kontroler główny jest najlepsze, jeśli nie musisz pokazywać modalu.
Używałem tego
let storyboard = UIStoryboard(name: "Main", bundle: nil) let vc = storyboard?.instantiateViewController(withIdentifier: "MainAppStoryboard") as! TabbarController present(vc, animated: false, completion: nil)
Używając tego zamiast tego z moim tabController:
let storyboard = UIStoryboard(name: "Main", bundle: nil) let view = storyboard.instantiateViewController(withIdentifier: "MainAppStoryboard") as UIViewController let appDelegate = UIApplication.shared.delegate as! AppDelegate //show window appDelegate.window?.rootViewController = view
Po prostu dostosuj się do kontrolera widoku, jeśli chcesz przełączać się między wieloma ekranami scenorysu.
źródło
Szybki 3.
Wywołaj tę funkcję, aby uzyskać najwyższy kontroler widoku, a następnie mieć obecny kontroler widoku.
func topMostController() -> UIViewController { var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController! while (topController.presentedViewController != nil) { topController = topController.presentedViewController! } return topController }
Stosowanie:
let topVC = topMostController() let vcToPresent = self.storyboard!.instantiateViewController(withIdentifier: "YourVCStoryboardID") as! YourViewController topVC.present(vcToPresent, animated: true, completion: nil)
źródło
dla SWIFT
func topMostController() -> UIViewController { var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController! while (topController.presentedViewController != nil) { topController = topController.presentedViewController! } return topController }
źródło
topController
zwracana przez tę funkcję jest dokładnie taka sama VC jakself
w przypadku próby prezentacji bezpośrednio przy użyciuself.presentViewController(myModalVC)
, ale nie ma błędu hierarchii widoku, gdy przekazuję prezentację VC za pomocą twojej funkcji.Wystarczy wykonać selektor z opóźnieniem - (działa 0 sekund).
override func viewDidLoad() { super.viewDidLoad() perform(#selector(presentExampleController), with: nil, afterDelay: 0) } @objc private func presentExampleController() { let exampleStoryboard = UIStoryboard(named: "example", bundle: nil) let exampleVC = storyboard.instantiateViewController(withIdentifier: "ExampleVC") as! ExampleVC present(exampleVC, animated: true) }
źródło
Szybki 4
func topMostController() -> UIViewController { var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController! while (topController.presentedViewController != nil) { topController = topController.presentedViewController! } return topController }
źródło
public static func getTopViewController() -> UIViewController?{ if var topController = UIApplication.shared.keyWindow?.rootViewController { while (topController.presentedViewController != nil) { topController = topController.presentedViewController! } return topController } return nil}
źródło
Otrzymałem ten błąd podczas prezentowania kontrolera po otwarciu przez użytkownika głębokiego linku. Wiem, że to nie jest najlepsze rozwiązanie, ale jeśli jesteś w krótkim czasie, tutaj jest szybka poprawka - po prostu zawiń kod
asyncAfter
:DispatchQueue.main.asyncAfter(deadline: .now() + 0.7, execute: { [weak self] in navigationController.present(signInCoordinator.baseController, animated: animated, completion: completion) })
Daje to czas na wywołanie kontrolera prezentacji
viewDidAppear
.źródło
let storyboard = UIStoryboard(name: "test", bundle: nil) let vc = storyboard.instantiateViewController(withIdentifier: "teststoryboard") as UIViewController UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true, completion: nil)
Wydawało się, że to działa, aby upewnić się, że jest to najwyższy widok.
Otrzymałem błąd
Mam nadzieję, że pomoże to innym w szybkim 3
źródło
Próbowałem tak wielu sposobów! jedyną przydatną rzeczą jest:
if var topController = UIApplication.shared.keyWindow?.rootViewController { while (topController.presentedViewController != nil) { topController = topController.presentedViewController! } }
źródło
Wszystkie implementacje dla topViewController tutaj nie w pełni obsługują przypadki, gdy masz
UINavigationController
lubUITabBarController
, dla tych dwóch, potrzebujesz nieco innej obsługi:Do
UITabBarController
iUINavigationController
potrzebujesz innej implementacji.Oto kod, którego używam do pobrania topMostViewController:
protocol TopUIViewController { func topUIViewController() -> UIViewController? } extension UIWindow : TopUIViewController { func topUIViewController() -> UIViewController? { if let rootViewController = self.rootViewController { return self.recursiveTopUIViewController(from: rootViewController) } return nil } private func recursiveTopUIViewController(from: UIViewController?) -> UIViewController? { if let topVC = from?.topUIViewController() { return recursiveTopUIViewController(from: topVC) ?? from } return from } } extension UIViewController : TopUIViewController { @objc open func topUIViewController() -> UIViewController? { return self.presentedViewController } } extension UINavigationController { override open func topUIViewController() -> UIViewController? { return self.visibleViewController } } extension UITabBarController { override open func topUIViewController() -> UIViewController? { return self.selectedViewController ?? presentedViewController } }
źródło
Poprzednie odpowiedzi dotyczą sytuacji, w której kontroler widoku, który powinien przedstawiać widok 1) nie został jeszcze dodany do hierarchii widoków, lub 2) nie jest kontrolerem widoku z góry.
Inną możliwością jest to, że ostrzeżenie powinno być prezentowane, gdy inny ostrzeżenie jest już prezentowane i jeszcze nie zostało odrzucone.
źródło
Swift Method i dostarcz demo.
func topMostController() -> UIViewController { var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController! while (topController.presentedViewController != nil) { topController = topController.presentedViewController! } return topController } func demo() { let vc = ViewController() let nav = UINavigationController.init(rootViewController: vc) topMostController().present(nav, animated: true, completion: nil) }
źródło
Swift 5.1 :
let storyboard = UIStoryboard.init(name: "Main", bundle: Bundle.main) let mainViewController = storyboard.instantiateViewController(withIdentifier: "ID") let appDeleg = UIApplication.shared.delegate as! AppDelegate let root = appDeleg.window?.rootViewController as! UINavigationController root.pushViewController(mainViewController, animated: true)
źródło
Użycie głównego wątku do prezentowania i zamykania kontrolera widoku zadziałało dla mnie.
DispatchQueue.main.async { self.present(viewController, animated: true, completion: nil) }
źródło
Zamiast znajdować kontroler widoku z góry, można użyć
viewController.modalPresentationStyle = UIModalPresentationStyle.currentContext
Gdzie viewController jest kontrolerem który chcesz zaprezentować Jest to przydatne gdy w hierarchii są różne rodzaje widoków jak TabBar, NavBar chociaż inne wydają się być poprawne ale bardziej hakerskie
Inny styl prezentacji można znaleźć w Apple Doc
źródło