警告:尝试在视图不在窗口层次结构中的* on *上显示 - swift

时间:2014-09-24 17:14:57

标签: ios swift hierarchy presentviewcontroller

如果数据模型中有任何已保存的数据,我正在尝试提供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找到了不同的解决方案但没有成功。

17 个答案:

答案 0 :(得分:115)

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

答案 1 :(得分:33)

在目标c中: 这在mpmovieplayer

之上呈现viewcontroller时解决了我的问题
- (UIViewController*) topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

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

    return topController;
}

答案 2 :(得分:31)

Swift 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

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

答案 3 :(得分: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) 
}

答案 4 :(得分:13)

斯威夫特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)

答案 5 :(得分:10)

for SWIFT

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

答案 6 :(得分:5)

Swift 4

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

答案 7 :(得分:2)

  

对于swift 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}

答案 8 :(得分:1)

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

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

答案 9 :(得分:1)

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

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

这将使您的主持人有时间呼叫viewDidAppear

答案 10 :(得分:1)

当你拥有UINavigationControllerUITabBarController时,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
    }
}

答案 11 :(得分:1)

我已经尝试过这么多的方法!唯一有用的是:

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

答案 12 :(得分: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上显示myapp.testController:0x7fdd01703990:0x7fdd01703690,其视图不在窗口层次结构中!

希望这可以帮助其他人快速3

答案 13 :(得分:0)

不是找到顶视图控制器,而是可以使用

viewController.modalPresentationStyle = UIModalPresentationStyle.currentContext

其中viewController是您要呈现的控制器 当像TabBar,NavBar这样的层次结构中存在不同类型的视图时,这很有用,尽管其他视图似乎是正确的但更多的是hackish

其他演示文稿样式可在apple doc

上找到

答案 14 :(得分:0)

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

答案 15 :(得分:0)

快速方法,并提供演示。

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

答案 16 :(得分: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)