警告:尝试在*不在窗口层次结构中的*上显示*


83

我正在尝试提出数据模型中ViewController 是否有任何保存的数据。但是我收到以下错误:

警告:尝试在*其视图不在窗口层次结构中显示*

相关代码:

override func viewDidLoad() {
    super.viewDidLoad()
    loginButton.backgroundColor = UIColor.orangeColor()

    var request = NSFetchRequest(entityName: "UserData")
    request.returnsObjectsAsFaults = false

    var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
    var context:NSManagedObjectContext = appDel.managedObjectContext!

    var results:NSArray = context.executeFetchRequest(request, error: nil)!

    if(results.count <= 0){
        print("Inga resultat")
    } else {
        print("SWITCH VIEW PLOX")
        let internVC = self.storyboard?.instantiateViewControllerWithIdentifier("internVC") as internViewController
        self.presentViewController(internVC, animated: true, completion: nil)
    }
}

我尝试过使用Google找到的其他解决方案,但均未成功。


您是否已在Storyboard中连接ViewController?您在这里使用NavigationController吗?
德里达

如果我ViewController在Storyboard中连接了我,那是什么意思?我没有使用NavigationController@derdida
Nils Wasell 2014年

试试:ViewDidLoad中的self.addChildViewController(childController:UIViewController)
德里达

这会产生一个错误。它期望在“类型名称”(该UIViewController部分)之后调用成员名称或构造函数。@derdida
Nils Wasell 2014年

你在哪写的 在您的MainViewController的ViewDidLoad中?
derdida 2014年

Answers:


126

此时,在代码中,视图控制器的视图仅已创建,但未添加到任何视图层次结构中。如果您希望尽快从该视图控制器中进行显示,则应该这样做viewDidAppear是最安全的。


2
如果我将其放在viewDidAppear中,那么当我关闭presentedViewController时,它将再次调用viewDidAppear方法并再次显示viewController。条件语句?
Puneet

2
我要说的是,尝试在屏幕出现时提出另一种模式权利一开始就很奇怪,因此状态布尔并不是最糟糕的解决方案。同时,考虑需要显示模式的根本原因,并查看是否可以访问该信息。
阿西2014年

2
如果在viewWillAppear中执行此操作,则在开始演示时会处于演示中间的情况。另一种方法是将其放在viewWillAppear中,但使用iOS 8中新增的transitionCoordinator属性在过渡完成时添加代码。更多信息可以在这里找到developer.apple.com/library/prerelease/ios/documentation/UIKit/...
Acey

36

在目标c中:当在mpmovieplayer上显示viewcontroller时,这解决了我的问题

- (UIViewController*) topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }

    return topController;
}

34

迅捷3

我一直是新手,发现当前的加载模态视图可以取消,但是如果不需要显示模态,最好切换到根控制器。

我在用这个

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc  = storyboard?.instantiateViewController(withIdentifier: "MainAppStoryboard") as! TabbarController
present(vc, animated: false, completion: nil)

与我的tabController一起使用:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let view = storyboard.instantiateViewController(withIdentifier: "MainAppStoryboard") as UIViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
//show window
appDelegate.window?.rootViewController = view

如果需要在多个故事板屏幕之间切换,只需调整为视图控制器即可。


16

雨燕3。

调用此函数以获取最顶层的视图控制器,然后使该视图控制器存在。

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
        while (topController.presentedViewController != nil) {
            topController = topController.presentedViewController!
        }
        return topController
    }

用法:

let topVC = topMostController()
let vcToPresent = self.storyboard!.instantiateViewController(withIdentifier: "YourVCStoryboardID") as! YourViewController
topVC.present(vcToPresent, animated: true, completion: nil)

1
感谢@Jacob Davis!我用它来呈现alertController因为我居然也得到了警告:试图提出....
加里Mansted

这非常有用。一些正在呈现的控制器但是屏幕没有出现。突然被解雇了。还有其他代码需要实现吗?请建议
Seethalakshmi_user8943692

13

用于SWIFT

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}

1
谢谢!这是唯一为我解决此错误的方法。我试图在手势完全加载视图之后(在Xcode 8 / iOS 10中)通过手势识别器触发的功能呈现模式VC。奇怪的是,topController此函数返回的是与self尝试直接使用时完全相同的VC self.presentViewController(myModalVC),但是当我使用您的函数传入呈现VC时,没有视图层次结构错误。
Natalia

13

您只需要延迟执行选择器即可(0秒有效)。

override func viewDidLoad() {
    super.viewDidLoad()
    perform(#selector(presentExampleController), with: nil, afterDelay: 0)
}

@objc private func presentExampleController() {
    let exampleStoryboard = UIStoryboard(named: "example", bundle: nil)
    let exampleVC = storyboard.instantiateViewController(withIdentifier: "ExampleVC") as! ExampleVC
    present(exampleVC, animated: true) 
}

非常感谢。我在这个问题上停留了一个多小时。
Reza

谢谢... @objc func presentExampleController()
威廉·蔡

我认为这是一个了不起的答案!
mazend

那是一个hack(现在可能会起作用),但是会让您为在意外情况下中断的事情做好准备。
威廉·格兰德,

6

斯威夫特4

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}

1
的解释和示例将是有益的@AllenWixted
埃里·佩雷斯Beltré

2

适用于3.0或更高版本

public static func getTopViewController() -> UIViewController?{
if var topController = UIApplication.shared.keyWindow?.rootViewController
{
  while (topController.presentedViewController != nil)
  {
    topController = topController.presentedViewController!
  }
  return topController
}
return nil}

2

用户打开深度链接后,在显示控制器时出现此错误。我知道这不是最好的解决方案,但是如果您的时间较短,可以快速解决-将代码包装在asyncAfter

DispatchQueue.main.asyncAfter(deadline: .now() + 0.7, execute: { [weak self] in
                                navigationController.present(signInCoordinator.baseController, animated: animated, completion: completion)
                            })

这将给您的演示控制器打电话的时间viewDidAppear


1
let storyboard = UIStoryboard(name: "test", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "teststoryboard") as UIViewController
UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true, completion: nil)

这似乎可以确保它是最顶层的视图。

我遇到一个错误

警告:尝试在其视图不在窗口层次结构中的myapp.testController:0x7fdd01703690上显示myapp.testController:0x7fdd01703990!

希望这对其他人有帮助3


1

我尝试了很多方法!唯一有用的是:

if var topController = UIApplication.shared.keyWindow?.rootViewController
{
  while (topController.presentedViewController != nil)
  {
    topController = topController.presentedViewController!
  }
}

1

当您拥有UINavigationController或时UITabBarController,此处topViewController的所有实现都不完全支持情况,对于这两种情况,您需要一些不同的处理方式:

对于UITabBarControllerUINavigationController您需要不同的实现。

这是我用来获取topMostViewController的代码:

protocol TopUIViewController {
    func topUIViewController() -> UIViewController?
}

extension UIWindow : TopUIViewController {
    func topUIViewController() -> UIViewController? {
        if let rootViewController = self.rootViewController {
            return self.recursiveTopUIViewController(from: rootViewController)
        }

        return nil
    }

    private func recursiveTopUIViewController(from: UIViewController?) -> UIViewController? {
        if let topVC = from?.topUIViewController() { return recursiveTopUIViewController(from: topVC) ?? from }
        return from
    }
}

extension UIViewController : TopUIViewController {
    @objc open func topUIViewController() -> UIViewController? {
        return self.presentedViewController
    }
}

extension UINavigationController {
    override open func topUIViewController() -> UIViewController? {
        return self.visibleViewController
    }
}

extension UITabBarController {
    override open func topUIViewController() -> UIViewController? {
        return self.selectedViewController ?? presentedViewController
    }
}

1

Swift方法,并提供一个演示。

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}

func demo() {
    let vc = ViewController()
    let nav = UINavigationController.init(rootViewController: vc)
    topMostController().present(nav, animated: true, completion: nil)
}

1

使用主线程来显示和关闭视图控制器对我有用。

DispatchQueue.main.async { self.present(viewController, animated: true, completion: nil) }

0

与其寻找顶视图控制器,不如使用

viewController.modalPresentationStyle = UIModalPresentationStyle.currentContext

其中viewController是要显示的控制器,这在层次结构中存在不同类型的视图(例如TabBar,NavBar)时很有用,尽管其他视图似乎是正确的,但更令人讨厌

可以在Apple Doc上找到其他演示样式


0

先前的答案与以下情况有关:应提供视图的视图控制器1)尚未添加到视图层次结构,或2)不是顶视图控制器。
另一种可能性是,应在已经提出但尚未解除的另一条警告的同时提出警告。


0

Swift 5.1

let storyboard = UIStoryboard.init(name: "Main", bundle: Bundle.main)
let mainViewController = storyboard.instantiateViewController(withIdentifier: "ID")
let appDeleg = UIApplication.shared.delegate as! AppDelegate
let root = appDeleg.window?.rootViewController as! UINavigationController
root.pushViewController(mainViewController, animated: true)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.