刚开始使用Xcode 4.5,我在控制台得到了这个错误:

警告:试图在< ViewController: 0x1ec3e000>上显示< finishViewController: 0x1e56e0a0 >,其视图不在窗口层次结构中!

视图仍在显示,应用程序中的一切都在正常工作。这是iOS 6的新功能吗?

这是我用来在视图之间更改的代码:

UIStoryboard *storyboard = self.storyboard;
finishViewController *finished = 
[storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];

[self presentViewController:finished animated:NO completion:NULL];

当前回答

另一个潜在原因:

当我不小心两次呈现同一个视图控制器时,我就遇到了这个问题。(第一次使用performSegueWithIdentifer:sender:当按钮被按下时调用,第二次使用直接连接到按钮的segue)。

实际上,两个segue同时被触发,我得到了错误:试图在Y上显示X,其视图不在窗口层次结构中!

其他回答

当从嵌入在容器中的视图控制器执行segue时,你也可以得到这个警告。正确的解决方案是从容器的父容器使用segue,而不是从容器的视图控制器。

我修复了这个错误,将最顶部的视图控制器存储为常量,这是在rootViewController的while循环中发现的:

if var topController = UIApplication.shared.keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }
    topController.present(controller, animated: false, completion: nil)
    // topController should now be your topmost view controller
}

另一个潜在原因:

当我不小心两次呈现同一个视图控制器时,我就遇到了这个问题。(第一次使用performSegueWithIdentifer:sender:当按钮被按下时调用,第二次使用直接连接到按钮的segue)。

实际上,两个segue同时被触发,我得到了错误:试图在Y上显示X,其视图不在窗口层次结构中!

你只能有1个rootViewController,它是最近出现的一个。所以不要尝试让一个视图控制器呈现另一个视图控制器当它已经呈现了一个没有被解散的视图控制器。

在做了一些自己的测试之后,我得出了一个结论。

如果你有一个rootViewController你想要显示所有东西,那么你就会遇到这个问题。

下面是我的rootController代码(打开是从根节点显示视图控制器的快捷方式)。

func open(controller:UIViewController)
{
    if (Context.ROOTWINDOW.rootViewController == nil)
    {
        Context.ROOTWINDOW.rootViewController = ROOT_VIEW_CONTROLLER
        Context.ROOTWINDOW.makeKeyAndVisible()
    }

    ROOT_VIEW_CONTROLLER.presentViewController(controller, animated: true, completion: {})
}

如果我在一行中调用open两次(不管时间流逝),这将在第一个开放上工作,但不是在第二个开放上。第二次打开尝试将导致上述错误。

然而,如果我关闭最近呈现的视图然后调用open,当我再次调用open(在另一个视图控制器上)时,它工作得很好。

func close(controller:UIViewController)
{
    ROOT_VIEW_CONTROLLER.dismissViewControllerAnimated(true, completion: nil)
}

我的结论是,只有MOST-RECENT-CALL的rootViewController在视图层次结构上(即使您没有解散它或删除视图)。我试着玩所有的加载器调用(viewDidLoad, viewDidAppear,并做延迟调度调用),我发现我能让它工作的唯一方法是从最顶层的视图控制器调用present。

我在Swift 4.2上也有类似的问题,但我的观点没有从视图周期中呈现出来。我发现我有多个segue要同时呈现。所以我使用dispatchAsyncAfter。

func updateView() {

 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in

// for programmatically presenting view controller 
// present(viewController, animated: true, completion: nil)

//For Story board segue. you will also have to setup prepare segue for this to work. 
 self?.performSegue(withIdentifier: "Identifier", sender: nil)
  }
}