尝试呈现其视图不在Windows层次结构中的ViewController

时间:2016-10-28 11:46:47

标签: ios swift

我遇到一个奇怪的问题:我制作了2个视图控制器,我可以用代码切换视图:

var currentViewController:UIViewController=UIApplication.shared.keyWindow!.rootViewController!

func showController()
{
    let ViewControllernew1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewController2")

    currentViewController.present(ViewControllernew1, animated: true, completion: nil)

}

我的应用程序正确打开第一个视图控制器,然后,当我点击精灵工具包场景中创建的按钮时,我可以成功地将视图切换到我的新视图控制器(我成功显示了第二个场景)但是然后,此切换后我无法再更改视图控制器。如果我再次点击按钮,我收到此消息:

尝试在Test_Vuforia.GameViewController上显示:0x12f549610,其视图不在窗口层次结构中!

你知道这是什么问题吗?我知道我处于根本位置,以便在切换之后我不能再改变我的视图控制器,但是如何改变它?

谢谢!

编辑:

我的代码在SKScene中使用,而不是在UIVewController中使用,当我使用后缀self时,我收到此错误。 :View类型的值(SKScene)没有成员'present'。

我正在用Vuforia创建一个增强现实游戏,我需要用SKScene切换AR视图。

6 个答案:

答案 0 :(得分:27)

问题

当前的viewController不是来自rootViewController的{​​{1}}。所以你应该找到当前可见的viewController然后从那里呈现它。

解决方案

只需在UIApplication上找到topViewController,然后从那里找到您的控制器。

UIApplication Stack

let newViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewController2") UIApplication.topViewController()?.present(newViewController, animated: true, completion: nil) 的扩展名为您的案例派上用场

UIApplication

参考文献:Gist

答案 1 :(得分:3)

viewDidAppear 中调用函数有助于我的情况。解决方案 Swift 3

在主控制器中:

MFMailComposerViewController

在您的教程控制器中:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    showTutorialModally()
}

func showTutorialModally() {
    let tutorialViewController = TutorialViewController()
    tutorialViewController.modalPresentationStyle = .overCurrentContext
    present(tutorialViewController, animated: true, completion: nil)
}

答案 2 :(得分:2)

使用下面的扩展名检索堆栈中的下一个可用控制器。

Swift 3

extension UIResponder {
    func next<T: UIResponder>(_ type: T.Type) -> T? {
        return next as? T ?? next?.next(type)
    }
}

Swift 2.3

extension UIResponder {
    func nextResponder<T: UIResponder>(_ type: T.Type) -> T? {
        return nextResponder() as? T ?? nextResponder()?.nextResponder(type)
    }
}

SKScene内,view?.next(UIViewController.self)为您提供层次结构中的下一个UIViewController

将此扩展名添加到项目中名为“类别”的组中,如果该组尚未创建,则创建一个名为UIResponder+NextOfType.swift的新文件并粘贴扩展名。

答案 3 :(得分:2)

粗略的Xcode错误重要性:此视图不在视图层次结构的窗口中。

我不会想到上面的回答问题,但也许你可能想知道为什么会这样。

但我发现你是这个问题的原因很可能是在ViewController生命周期中的ViewDidLoading切换视图中执行代码。

原因可能是,当初始化期间ViewController实现allco init时,它将异步执行viewWillLoad - &gt; viewDidLoad ... - - - - &gt; viewDidApper。然后可能在viewDidLoad的代码执行中。 ViewController可能不会为Window分配值。 rootViewController。所以我们直接使用[self presentViewController:]会出现这个错误。

建议您将开关的代码移动到ViewDidApper。

我希望它会对你有所帮助。

答案 4 :(得分:1)

像这样使用

let vc = self.view?.window?.rootViewController
func showController()
{
    let ViewControllernew1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewController2")

    vc.present(ViewControllernew1, animated: true, completion: nil)
}

问题可能出在currentViewController上。

答案 5 :(得分:1)

  1. 您的rootViewController可能不是当前的ViewController。您可以在其上面展示或推送一个新的UIViewController。

  2. viewController's视图不在 窗口的视图层次结构在它已加载的时间点(何时 发送viewDidLoad消息),但它在窗口中 提交后的层次结构(viewDidAppear时: 消息被发送)。 如果您从中调用showController方法 viewDidLoad只需从viewDidAppear方法

  3. 调用它即可

    做类似的事情:

     let vc: UIViewController = (self.storyboard?.instantiateViewControllerWithIdentifier("viewController2"))!
     self.presentViewController(vc, animated: true, completion: nil)
    
     // OR
     self.navigationController?.pushViewController(vc, animated: true)