ios 尝试在视图不在窗口层次结构中的 UIViewController 上显示 UIViewController

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11862883/
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-30 19:38:41  来源:igfitidea点击:

Attempt to present UIViewController on UIViewController whose view is not in the window hierarchy

ioscocoa-touchios6viewshierarchy

提问by Kyle Goslan

Just started using Xcode 4.5 and I got this error in the console:

刚开始使用 Xcode 4.5,我在控制台中收到此错误:

Warning: Attempt to present < finishViewController: 0x1e56e0a0 > on < ViewController: 0x1ec3e000> whose view is not in the window hierarchy!

警告:尝试在视图不在窗口层次结构中的 < ViewController: 0x1ec3e000> 上呈现 < finishViewController: 0x1e56e0a0 > !

The view is still being presented and everything in the app is working fine. Is this something new in iOS 6?

该视图仍在呈现,应用程序中的一切正常。这是 iOS 6 中的新功能吗?

This is the code I'm using to change between views:

这是我用来在视图之间切换的代码:

UIStoryboard *storyboard = self.storyboard;
finishViewController *finished = 
[storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];

[self presentViewController:finished animated:NO completion:NULL];

回答by James Bedford

Where are you calling this method from? I had an issue where I was attempting to present a modal view controller within the viewDidLoadmethod. The solution for me was to move this call to the viewDidAppear:method.

你从哪里调用这个方法?我在尝试在方法中呈现模态视图控制器时遇到了问题viewDidLoad。我的解决方案是将此调用移至该viewDidAppear:方法。

My presumption is that the view controller's view is notin the window's view hierarchy at the point that it has been loaded (when the viewDidLoadmessage is sent), but it isin the window hierarchy after it has been presented (when the viewDidAppear:message is sent).

我的假设是视图控制器的观点是不是在窗口的视图层次的,它已经加载点(当viewDidLoad发送邮件),但它在窗口层次结构已经呈现后(当viewDidAppear:发送消息) .



Caution

警告

If you do make a call to presentViewController:animated:completion:in the viewDidAppear:you may run into an issue whereby the modal view controller is always being presented whenever the view controller's view appears (which makes sense!) and so the modal view controller being presented will never go away...

如果您确实调用presentViewController:animated:completion:inviewDidAppear:您可能会遇到一个问题,即每当视图控制器的视图出现时,模态视图控制器总是被呈现(这是有道理的!),因此被呈现的模态视图控制器永远不会消失.. .

Maybe this isn't the best place to present the modal view controller, or perhaps some additional state needs to be kept which allows the presenting view controller to decide whether or not it should present the modal view controller immediately.

也许这不是呈现模态视图控制器的最佳位置,或者可能需要保留一些额外的状态,以允许呈现视图控制器决定是否应该立即呈现模态视图控制器。

回答by Chris Nolet

Another potential cause:

另一个潜在原因:

I had this issue when I was accidentally presenting the same view controller twice. (Once with performSegueWithIdentifer:sender:which was called when the button was pressed, and a second time with a segue connected directly to the button).

当我不小心两次呈现相同的视图控制器时,我遇到了这个问题。(performSegueWithIdentifer:sender:当按下按钮时调用一次,第二次使用直接连接到按钮的 segue)。

Effectively, two segues were firing at the same time, and I got the error: Attempt to present X on Y whose view is not in the window hierarchy!

实际上,两个 segue 同时触发,我得到了错误: Attempt to present X on Y whose view is not in the window hierarchy!

回答by Jonny

viewWillLayoutSubviewsand viewDidLayoutSubviews(iOS 5.0+) can be used for this purpose. They are called earlier than viewDidAppear.

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

回答by abdul sathar

For Display any subview to main view,Please use following code

要将任何子视图显示到主视图,请使用以下代码

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

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

[yourCurrentViewController presentViewController:composeViewController animated:YES completion:nil];

For Dismiss any subview from main view,Please use following code

对于从主视图中关闭任何子视图,请使用以下代码

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

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

[yourCurrentViewController dismissViewControllerAnimated:YES completion:nil];

回答by sunkehappy

I also encountered this problem when I tried to present a UIViewControllerin viewDidLoad. James Bedford's answer worked, but my app showed the background first for 1 or 2 seconds.

当我尝试UIViewControllerviewDidLoad. James Bedford 的回答有效,但我的应用程序首先显示了 1 或 2 秒的背景。

After some research, I've found a way to solve this using the addChildViewController.

经过一番研究,我找到了一种使用addChildViewController.

- (void)viewDidLoad
{
    ...
    [self.view addSubview: navigationViewController.view];
    [self addChildViewController: navigationViewController];
    ...
}

回答by Sanbrother

Probably, like me, you have a wrong root viewController

可能和我一样,你有一个错误的根 viewController

I want to display a ViewControllerin a non-UIViewControllercontext,

我想ViewControllernon-UIViewController上下文中显示一个,

So I can't use such code:

所以我不能使用这样的代码:

[self presentViewController:]

So, I get a UIViewController:

所以,我得到了一个 UIViewController:

[[[[UIApplication sharedApplication] delegate] window] rootViewController]

For some reason (logical bug), the rootViewControlleris something other than expected (a normal UIViewController). Then I correct the bug, replacing rootViewControllerwith a UINavigationController, and the problem is gone.

由于某种原因(逻辑错误),这rootViewController不是预期的(正常的UIViewController)。然后我更正了错误,替换rootViewControllerUINavigationController,问题就解决了。

回答by Aggressor

TL;DRYou can only have 1 rootViewController and its the most recently presented one. So don't try having a viewcontroller present another viewcontroller when it's already presented one that hasn't been dismissed.

TL;DR你只能有 1 个 rootViewController 和它最近出现的一个。因此,不要尝试让一个视图控制器呈现另一个视图控制器,因为它已经呈现了一个尚未被解雇的视图控制器。

After doing some of my own testing I've come to a conclusion.

在做了一些自己的测试之后,我得出了一个结论。

If you have a rootViewController that you want to present everything then you can run into this problem.

如果您有一个想要呈现所有内容的 rootViewController,那么您可能会遇到这个问题。

Here is my rootController code (open is my shortcut for presenting a viewcontroller from the root).

这是我的 rootController 代码(open 是我从根目录呈现视图控制器的快捷方式)。

func open(controller:UIViewController)
{
    if (Context.ROOTWINDOW.rootViewController == nil)
    {
        Context.ROOTWINDOW.rootViewController = ROOT_VIEW_CONTROLLER
        Context.ROOTWINDOW.makeKeyAndVisible()
    }

    ROOT_VIEW_CONTROLLER.presentViewController(controller, animated: true, completion: {})
}

If I call open twice in a row (regardless of time elapsed), this will work just fine on the first open, but NOT on the second open. The second open attempt will result in the error above.

如果我连续调用 open 两次(无论经过多少时间),这将在第一次打开时正常工作,但不会在第二次打开时正常工作。第二次打开尝试将导致上述错误。

However if I close the most recently presented view then call open, it works just fine when I call open again (on another viewcontroller).

但是,如果我关闭最近呈现的视图然后调用 open,当我再次调用 open (在另一个视图控制器上)时它工作得很好。

func close(controller:UIViewController)
{
    ROOT_VIEW_CONTROLLER.dismissViewControllerAnimated(true, completion: nil)
}

What I have concluded is that the rootViewController of only the MOST-RECENT-CALL is on the view Hierarchy (even if you didn't dismiss it or remove a view). I tried playing with all the loader calls (viewDidLoad, viewDidAppear, and doing delayed dispatch calls) and I have found that the only way I could get it to work is ONLY calling present from the top most view controller.

我得出的结论是,只有 MOST-RECENT-CALL 的 rootViewController 位于视图层次结构中(即使您没有关闭它或删除视图)。我尝试使用所有加载器调用(viewDidLoad、viewDidAppear 和延迟调度调用),我发现我可以让它工作的唯一方法是只从最顶层的视图控制器调用 present。

回答by Adam Johns

My issue was I was performing the segue in UIApplicationDelegate's didFinishLaunchingWithOptionsmethod before I called makeKeyAndVisible()on the window.

我的问题是我在调用窗口之前执行了 inUIApplicationDelegatedidFinishLaunchingWithOptions方法makeKeyAndVisible()

回答by George_E

In my situation, I was not able to put mine in a class override. So, here is what I got:

在我的情况下,我无法将我的置于类覆盖中。所以,这是我得到的:

let viewController = self // I had viewController passed in as a function,
                          // but otherwise you can do this


// Present the view controller
let currentViewController = UIApplication.shared.keyWindow?.rootViewController
currentViewController?.dismiss(animated: true, completion: nil)

if viewController.presentedViewController == nil {
    currentViewController?.present(alert, animated: true, completion: nil)
} else {
    viewController.present(alert, animated: true, completion: nil)
}

回答by saltwat5r

This kind of warning can mean that You're trying to present new View Controllerthrough Navigation Controllerwhile this Navigation Controlleris currently presenting another View Controller. To fix it You have to dismiss currently presented View Controllerat first and on completion present the new one. Another cause of the warning can be trying to present View Controlleron thread another than main.

这种警告可能意味着你正在尝试提出新的View Controller通过Navigation Controller,而这Navigation Controller是目前呈现的另一个View Controller。修复它你必须首先关闭当前呈现的View Controller,并在完成时呈现新的。警告的另一个原因可能是尝试View Controllermain.