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

当前回答

我也有同样的问题。问题是,performSegueWithIdentifier是由通知触发的,只要我把通知放在主线程上,警告消息就消失了。

其他回答

遗憾的是,这个公认的解决方案并不适用于我的案例。我试图在从另一个视图控制器unwind后导航到一个新的视图控制器。

我找到了一个解决方案,使用一个标志来指示哪个unwind segue被调用。

@IBAction func unwindFromAuthenticationWithSegue(segue: UIStoryboardSegue) {
    self.shouldSegueToMainTabBar = true
}

@IBAction func unwindFromForgetPasswordWithSegue(segue: UIStoryboardSegue) {
    self.shouldSegueToLogin = true
}

然后用present(_ viewcontrollertoppresent: UIViewController)来呈现想要的VC

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    if self.shouldSegueToMainTabBar {
        let mainTabBarController = storyboard.instantiateViewController(withIdentifier: "mainTabBarVC") as! MainTabBarController
        self.present(mainTabBarController, animated: true)
        self.shouldSegueToMainTabBar = false
    }
    if self.shouldSegueToLogin {
        let loginController = storyboard.instantiateViewController(withIdentifier: "loginVC") as! LogInViewController
        self.present(loginController, animated: true)
        self.shouldSegueToLogin = false
    }
}

基本上,上面的代码将让我从login/SignUp VC捕获unwind并导航到仪表板,或者从forget password VC捕获unwind操作并导航到登录页面。

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

它主要发生在你在一些后台工作后,如Api命中或特别核心数据服务调用警报。 在应用程序主线程中调用警报。

DispatchQueue.main.async {
   // call your alert in this main thread.
   Constants.alert(title: "Network Error!", message: "Please connect to internet and try again.", controller: self)
}

viewWillLayoutSubviews和viewDidLayoutSubviews (iOS 5.0+)可以用于此目的。它们在viewDidAppear之前被调用。

我通过将start()函数移动到解散完成块内部来修复它:

self.tabBarController.dismiss(animated: false) {
  self.start()
}

Start包含对self.present()的两个调用,一个用于UINavigationController,另一个用于UIImagePickerController。

这为我解决了问题。