刚开始使用Xcode 4.5,我在控制台中遇到了这个错误:
警告:尝试在<ViewController:0x1ec3e000>上显示<finishViewController:0x1e56e0a0>,其视图不在窗口层次结构中!
该视图仍在呈现,应用程序中的所有内容都正常运行 . 这是iOS 6中的新功能吗?
这是我用于在视图之间切换的代码:
UIStoryboard *storyboard = self.storyboard;
finishViewController *finished =
[storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];
[self presentViewController:finished animated:NO completion:NULL];
27 回答
我最终得到了这样一个代码,最终对我有用(Swift),考虑到你想从几乎任何地方显示一些
viewController
. 当没有rootViewController可用时,此代码显然会崩溃,这是开放式结尾 . 它也不包括通常需要切换到UI线程使用要显示主视图的任何子视图,请使用以下代码
要从主视图中关闭任何子视图,请使用以下代码
你在哪里调用这种方法?我有一个问题,我试图在
viewDidLoad
方法中呈现模态视图控制器 . 我的解决方案是将此调用移至viewDidAppear:
方法 .我的假设是视图控制器在窗口的视图层次结构中查看 is not 它已被加载的点(当发送
viewDidLoad
消息时),但它在窗口层次结构中显示 is (当发送viewDidAppear:
消息时) ) .Caution
如果您确实在
viewDidAppear:
中调用presentViewController:animated:completion:
,则可能会遇到一个问题,即每当视图控制器的视图出现时,模态视图控制器总是被呈现(这是有意义的!),因此呈现的模态视图控制器永远不会消失...也许这不是呈现模态视图控制器的最佳位置,或者可能需要保留一些额外的状态,这允许呈现视图控制器决定它是否应该立即呈现模态视图控制器 .
With Swift 3...
发生在我身上的另一个可能原因是,从一个tableViewCell到Storyboard上的另一个ViewController有一个segue . 单击单元格时,我也使用了
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {}
.我通过从ViewController到ViewController制作一个segue来解决这个问题 .
它发生在我身上 segue in the storyboard was some kind of broken . 删除segue(并再次创建完全相同的segue)解决了这个问题 .
可悲的是,接受的解决方案对我的案子不起作用 . 我正试图从另一个视图控制器退出后立即导航到新的视图控制器 .
我找到了一个解决方案,使用一个标志来指示调用了哪个展开segue .
然后用
present(_ viewControllerToPresent: UIViewController)
呈现想要的VC基本上,上面的代码将让我从login / SignUp VC中获取解除并导航到仪表板,或者从忘记密码VC中捕获展开操作并导航到登录页面 .
使用主窗口时,可能总会出现与显示警报不兼容的转换 . 为了允许在应用程序生命周期中随时显示警报,您应该有一个单独的窗口来完成工作 .
根据设计,将始终成功的基本用法:
如果您有播放视频的AVPlayer对象,则必须先暂停视频 .
如果其他解决方案由于某种原因看起来不太好,你仍然可以使用这个好的旧
workaround
表示延迟为0,如下所示:虽然我没有看到有文件证明你的VC会在调度块被安排执行时在视图层次结构上,但我发现它可以正常工作 .
使用例如延迟0.2秒也是一种选择 . 最好的事情 - 这样你就不需要在
viewDidAppear:
中弄乱布尔变量在我的情况下,我无法将其置于类覆盖中 . 所以,这是我得到的:
必须写下面的行 .
代替
在UIViewController中
我遇到过同样的问题 . 问题是,performSegueWithIdentifier是由通知触发的,只要我在主线程上发出通知警告消息就消失了 .
从嵌入容器的视图控制器执行segue时,也可以收到此警告 . 正确的解决方案是使用来自容器父级的segue,而不是容器的视图控制器 .
我的问题是我在窗口上调用
makeKeyAndVisible()
之前在UIApplicationDelegate
的didFinishLaunchingWithOptions
方法中执行了segue .我也有这个问题,但它与时间无关 . 我正在使用单例处理场景,我将其设置为演示者 . 换句话说,“自我”并没有被任何东西所吸引 . 我只是让它的内心“场景”成为新的主持人而且瞧,它奏效了 . (Voila在你了解它的含义后失去了它的触觉,呵呵) .
所以是的,这不是“神奇地找到正确的方法”,它是关于理解代码所处的位置以及它正在做什么 . 我很高兴苹果公司给出了这样一个简单的英语警告信息,即使对此情有独钟 . 感谢苹果开发者做到了!
viewWillLayoutSubviews
和viewDidLayoutSubviews
(iOS 5.0)可用于此目的 . 它们比viewDidAppear更早被调用 .我有同样的问题 . 我必须嵌入一个导航控制器并通过它呈现控制器 . 以下是示例代码 .
我已经尝试了很多答案,但没有人帮助我唯一能为我工作的解决方案是快速4解决方案<ViewController:0x1ec3e000>其视图不在窗口层次结构中!
TL;DR 您只能拥有1个rootViewController及其最近提供的rootViewController . 因此,已经提出了一个尚未被解雇的人 .
在做了一些我自己的测试后,我得出了一个结论 .
如果你有一个想要呈现所有内容的rootViewController,那么你可能会遇到这个问题 .
这是我的rootController代码(open是我从根目录呈现viewcontroller的快捷方式) .
如果我连续两次打开(无论时间是否已经过去),这将在第一次打开时正常工作,但不会在第二次打开时工作 . 第二次打开尝试将导致上述错误 .
但是,如果我关闭最近显示的视图然后调用open,当我再次调用open(在另一个viewcontroller上)时它可以正常工作 .
我得出的结论是,只有MOST-RECENT-CALL的rootViewController在视图Hierarchy上(即使你没有关闭它或删除一个视图) . 我尝试使用所有加载器调用(viewDidLoad,viewDidAppear,并执行延迟调度调用),我发现只有这样才能让它工作才能从最顶层的视图控制器调用present .
当我试图在
viewDidLoad
中呈现视图控制器时,我也遇到了这个问题 . 我_343217的答案 . 它可以工作,但我的应用程序将首先显示背景1或2秒 .经过研究我终于找到了解决这个问题的另一种方法是使用子视图控制器 .
它工作正常试试这个 . Link
另一个潜在原因:
当我意外地两次呈现相同的视图控制器时,我遇到了这个问题 . (一次是按下按钮时调用的
performSegueWithIdentifer:sender:
,第二次是直接连接按钮的segue) .实际上,两个segues同时开火,我得到了错误:
Attempt to present X on Y whose view is not in the window hierarchy!
万一它对任何人都有帮助,我的问题非常愚蠢 . 完全是我的错 . 通知正在触发调用模态的方法 . 但我没有正确删除通知,因此在某些时候,我会有多个通知,因此模式将被多次调用 . 当然,在您调用模态一次之后,调用它的视图控制器不再在视图层次结构中,这就是我们看到此问题的原因 . 正如您所料,我的情况也引发了许多其他问题 .
总而言之,无论你做什么 make sure the modal is not being called more than once .
可能和我一样,你的根本错了
viewController
我想在
non-UIViewController
上下文中显示ViewController
,So I can't use such code:
So, I get a UIViewController:
出于某种原因(逻辑错误),
rootViewController
不是预期的(正常的UIViewController
) . 然后我更正了错误,用UINavigationController
替换rootViewController
,问题就消失了 .我通过移动
dismiss
完成块内的start()
函数来修复它:Start包含两个对
self.present()
的调用,一个用于UINavigationController,另一个用于UIImagePickerController
.那为我修好了 .
这种警告可能意味着你正试图通过
Navigation Controller
呈现新的View Controller
,而Navigation Controller
目前正在呈现另一个View Controller
. 要修复它你必须首先解除当前显示的View Controller
,并在完成时显示新的 . 警告的另一个原因可能是尝试在View Controller
之外的线程上显示View Controller
.我有这个问题,根本原因是多次订阅按钮点击处理程序(TouchUpInside) .
它是在ViewWillAppear中订阅的,因为我们已添加导航到另一个控制器,然后展开回到它,因此被多次调用 .