刚开始使用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];

当前回答

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

其他回答

该消息显示为警告,有时代码拒绝工作。(!引文:更新的SDK可能有严格的规则)。

我遇到这种情况的原因不止一个,主要是复杂的视图控制器场景。举个例子。

Scenario: MainViewController (responsible to load: ViewControllerA & ViewControllerB)

从MainViewController中呈现ViewControllerA,并且在不解散ViewControllerA的情况下,尝试从MainViewController中呈现viewControllerB(使用委托方法)。

在这个场景中,你必须确保你的viewcontrollerera被解散,然后ViewControllerB被调用。

因为在呈现ViewControllerA之后(ViewControllerA开始负责显示视图和视图控制器,当MainViewController尝试加载另一个视图控制器时,它拒绝抛出警告)。

你从哪里调用这个方法?我有一个问题,我试图在viewDidLoad方法中呈现一个模态视图控制器。我的解决方案是将这个调用移动到viewDidAppear:方法。

我的假设是,视图控制器的视图在它被加载时(当viewDidLoad消息被发送时)不在窗口的视图层次结构中,但在它被呈现后(当viewDidAppear:消息被发送时)它在窗口层次结构中。


谨慎

如果你确实调用了viewDidAppear:中的presentViewController:animated:completion:,你可能会遇到这样一个问题,即每当视图控制器的视图出现时,模态视图控制器总是被呈现(这是有意义的!),因此模态视图控制器被呈现永远不会消失……

也许这不是呈现模态视图控制器的最佳位置,或者可能需要保留一些额外的状态让呈现的视图控制器决定是否应该立即呈现模态视图控制器。

当我试图在viewDidLoad中呈现一个UIViewController时,我也遇到了这个问题。James Bedford的答案是可行的,但我的应用程序先显示了1到2秒的背景。

经过一些研究,我找到了一种方法来解决这个使用addChildViewController。

- (void)viewDidLoad
{
    ...
    [self.view addSubview: navigationViewController.view];
    [self addChildViewController: navigationViewController];
    ...
}

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

这种警告可能意味着你正试图通过导航控制器呈现新的视图控制器,而这个导航控制器目前正在呈现另一个视图控制器。要修复它,你必须首先解散当前呈现的视图控制器,并在完成时呈现新的视图控制器。 警告的另一个原因可能是试图在主线程以外的线程上呈现视图控制器。