ios - Avvertenza: Tenta di presentare*su*la cui vista non è nella gerarchia della finestra: rapida




swift hierarchy (8)

Per Swift 3.0 e versioni successive

public static func getTopViewController() -> UIViewController?{
if var topController = UIApplication.shared.keyWindow?.rootViewController
{
  while (topController.presentedViewController != nil)
  {
    topController = topController.presentedViewController!
  }
  return topController
}
return nil}

Sto cercando di presentare un ViewController se nel modello dati sono presenti dati salvati. Ma ottengo il seguente errore:

Avviso: tentativo di presentare * su * la cui vista non è nella gerarchia della finestra "

Codice pertinente:

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)
    }
}

Ho provato diverse soluzioni trovate utilizzando Google senza successo.


A questo punto del codice, la vista del controller di visualizzazione è stata creata ma non aggiunta a nessuna gerarchia di viste. Se vuoi presentarti da quel controller di visualizzazione il prima possibile, dovresti farlo in viewDidAppear per essere più sicuro.


Ho provato così tanti approcci! l'unica cosa utile è:

if var topController = UIApplication.shared.keyWindow?.rootViewController
{
  while (topController.presentedViewController != nil)
  {
    topController = topController.presentedViewController!
  }
}

Nell'obiettivo c: questo ha risolto il mio problema presentando viewcontroller su mpmovieplayer

- (UIViewController*) topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }

    return topController;
}

Swift 3

Ho avuto questa continua a venire come un principiante e ho trovato che il presente carica viste modali che possono essere ignorati, ma il passaggio al controller di root è la cosa migliore se non è necessario mostrare una modale.

Stavo usando questo

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc  = storyboard?.instantiateViewController(withIdentifier: "MainAppStoryboard") as! TabbarController
present(vc, animated: false, completion: nil)

Usando questo invece con il mio 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

Basta regolare su un controller di visualizzazione se è necessario passare tra più schermate dello storyboard.


Swift 3.

Chiamare questa funzione per ottenere il controller di visualizzazione più in alto, quindi avere il controller di visualizzazione presente.

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
        while (topController.presentedViewController != nil) {
            topController = topController.presentedViewController!
        }
        return topController
    }

Uso:

let topVC = topMostController()
let vcToPresent = self.storyboard!.instantiateViewController(withIdentifier: "YourVCStoryboardID") as! YourViewController
topVC.present(vcToPresent, animated: true, completion: nil)

Tutte le implementazioni per topViewController qui non supportano completamente i casi quando hai UINavigationController o UITabBarController , per questi due hai bisogno di una gestione leggermente diversa:

Per UITabBarController e UINavigationController è necessaria una diversa implementazione.

Ecco il codice che sto usando per ottenere 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
    }
}

per SWIFT

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}




presentviewcontroller