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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40304405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 10:39:59  来源:igfitidea点击:

Attempt to present ViewController whose view is not in the windows hierarchy

iosswift

提问by PGibouin

I meet a strange problem: I made 2 view controllers for wich I can switch the view with code:

我遇到了一个奇怪的问题:我制作了 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)

}

My app open correctly to the first view controller, then, when I click on the button created on a sprite kit scene, I can switch the view to my new view controller successfully (I get my second scene successfully showed) but then, I can not change anymore my view controller after this switch. If I click again on the button, I get this message:

我的应用程序正确打开到第一个视图控制器,然后,当我单击在精灵套件场景上创建的按钮时,我可以成功地将视图切换到我的新视图控制器(我成功显示了我的第二个场景)但是,我可以在此切换后不再更改我的视图控制器。如果我再次单击该按钮,则会收到以下消息:

Attempt to present on Test_Vuforia.GameViewController: 0x12f549610 whose view is not in the window hierarchy!

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

Do you know what is the problem ? I understand I'm in the root position so that I can not change anymore my view controller after having switched it, but how to change that ?

你知道是什么问题吗?我知道我处于根位置,因此在切换视图控制器后我无法再更改它,但是如何更改它?

Thanks !

谢谢 !

Edit:

编辑:

My code is used inside a SKScene and not from a UIVewController and I get this error when I use the suffix self. : Value of type View (SKScene) has no member 'present'.

我的代码在 SKScene 中使用,而不是来自 UIVewController,当我使用后缀 self. : View (SKScene) 类型的值没有成员“present”。

I'm creating an augmented reality game with Vuforia and I need to switch AR view with SKScene.

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

回答by E-Riddie

Issue

问题

Current viewController is not the rootViewControllerfrom UIApplication. So you should find the current viewController which is visible and then present it from there.

当前 viewController 不是rootViewControllerfrom UIApplication。所以你应该找到当前可见的 viewController,然后从那里呈现它。

Solution

解决方案

Simply find the topViewController on your UIApplication Stack, and from there present your controller.

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

let newViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewController2")
UIApplication.topViewController()?.present(newViewController, animated: true, completion: nil)

This extension of UIApplicationcomes in handy for your case

这个扩展UIApplication对你的情况很有用

extension UIApplication {
    class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController {
            return topViewController(base: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController {
                return topViewController(base: selected)
            }
        }
        if let presented = base?.presentedViewController {
            return topViewController(base: presented)
        }
        return base
    }
}

References: Gist

参考资料:要点

回答by janaz

Calling function in viewDidAppearhelps in my case. Solution for Swift 3:

viewDidAppear 中调用函数对我有帮助。Swift 3 的解决方案:

In your Main Controller:

在您的主控制器中:

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

    showTutorialModally()
}

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

In your Tutorial Controller:

在您的教程控制器中:

view.backgroundColor = UIColor.clear
view.isOpaque = false

回答by Jersey

Xcode error significance for roughly: this view is not in the Window of the view hierarchy.

Xcode 的错误含义大致为:这个视图不在视图层次结构的 Window 中。

What I don't think the above answer questions, but maybe you might have wondered why this would happen.

我不认为上面的问题回答了什么,但也许你可能想知道为什么会发生这种情况。

But I find that you are the reasons for this problem is likely to be in the ViewController life cycle at ViewDidLoading switch view Code execution inside.

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

Reason is probably that, when the ViewController implementation allco init during initialization, it will be executed asynchronously viewWillLoad - > viewDidLoad... -- -- -- -- > viewDidApper. Then may be in code execution to the viewDidLoad. The ViewController may not assign values to the Window. The rootViewController. So we directly use [self presentViewController:] will appear this error.

原因大概是,ViewController在初始化时执行allco init时,会异步执行viewWillLoad -> viewDidLoad... -- -- -- --> viewDidApper。然后可能会在代码中执行到viewDidLoad。ViewController 可能不会为 Window 分配值。根视图控制器。所以我们直接使用[self presentViewController:]会出现这个错误。

It is recommended that you move the code of the switch to ViewDidApper.

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

I hope it will help you.

我希望它会帮助你。

回答by Callam

Use the extension below to retrieve the next available controller in the stack.

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

Swift 3

斯威夫特 3

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

Swift 2.3

斯威夫特 2.3

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

Inside your SKScene, view?.next(UIViewController.self)gives you the next available UIViewControllerin the hierarchy.

在 your 中SKSceneview?.next(UIViewController.self)为您提供UIViewController层次结构中的下一个可用。

Add this extension to a group in your project called Categories, if this group does not exist already create it, then create a new file called UIResponder+NextOfType.swiftand paste the extension.

将此扩展名添加到项目中名为 Categories 的组中,如果该组不存在,则创建它,然后创建一个名为的新文件UIResponder+NextOfType.swift并粘贴该扩展名。

回答by vaibhav

  1. Probably your rootViewControlleris not the current ViewController. Either you presented or pushed a new UIViewController on top of it.

  2. The viewController'sview is not in the window's view hierarchy at the point that it has been loaded (when the viewDidLoadmessage is sent), but it is in the window hierarchy after it has been presented (when the viewDidAppear: message is sent). if you calling showControllermethod from viewDidLoadjust call it from viewDidAppearmethod

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

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

Do something like:

做类似的事情:

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


 // OR
 self.navigationController?.pushViewController(vc, animated: true)

回答by Parth Adroja

Use like this

像这样使用

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

Maybe the issue is with the currentViewController.

也许问题出在 currentViewController 上。