警告:尝试在其视图不在窗口层次结构中的 * 上呈现 * - swift
Posted
技术标签:
【中文标题】警告:尝试在其视图不在窗口层次结构中的 * 上呈现 * - swift【英文标题】:Warning: Attempt to present * on * whose view is not in the window hierarchy - swift 【发布时间】:2014-11-19 07:01:03 【问题描述】:我正在尝试提供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 吗? 如果我在 Storyboard 中连接了我的ViewController
,这对你意味着什么?我没有使用NavigationController
@derdida
尝试:ViewDidLoad中的self.addChildViewController(childController: UIViewController)
这会产生错误。它需要在“类型名称”(UIViewController
部分)之后调用成员名称或构造函数。 @derdida
你在哪里写的?在 MainViewController 的 ViewDidLoad 中?
【参考方案1】:
使用主线程呈现和关闭视图控制器对我有用。
DispatchQueue.main.async self.present(viewController, animated: true, completion: nil)
【讨论】:
【参考方案2】: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)
【讨论】:
【参考方案3】: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)
【讨论】:
【参考方案4】:前面的答案与应该呈现视图的视图控制器 1) 尚未添加到视图层次结构中,或 2) 不是顶部视图控制器的情况有关。 另一种可能性是,应该在另一个警报已经出现但尚未解除的同时显示一个警报。
【讨论】:
【参考方案5】:我在用户打开深层链接后呈现控制器时收到此错误。
我知道这不是最好的解决方案,但如果您在短时间内可以快速解决 - 只需将您的代码包装在 asyncAfter
:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7, execute: [weak self] in
navigationController.present(signInCoordinator.baseController, animated: animated, completion: completion)
)
您的演示控制器将有时间致电viewDidAppear
。
【讨论】:
【参考方案6】:您只需要延迟执行选择器 - (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)
【讨论】:
非常感谢。我被这个问题困了一个多小时。 谢谢... @objc func presentExampleController() 我认为这是一个了不起的答案! 这是一个 hack(现在可能有效),但会让您在意外情况下遇到问题。【参考方案7】:不用找顶视图控制器,可以使用
viewController.modalPresentationStyle = UIModalPresentationStyle.currentContext
其中 viewController 是您要呈现的控制器 这在层次结构中有不同类型的视图(如 TabBar、NavBar)时很有用,尽管其他视图似乎是正确的,但更像是 hackish
其他演示风格可以在apple doc找到
【讨论】:
【参考方案8】:当您有UINavigationController
或UITabBarController
时,这里所有topViewController 的实现都不是完全支持的情况,对于这两种情况,您需要稍微不同的处理方式:
对于UITabBarController
和UINavigationController
,您需要不同的实现。
这是我用来获取 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
【讨论】:
【参考方案9】:斯威夫特 4
func topMostController() -> UIViewController
var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
while (topController.presentedViewController != nil)
topController = topController.presentedViewController!
return topController
【讨论】:
解释和示例会很有帮助@AllenWixted【参考方案10】:我尝试了很多方法!唯一有用的是:
if var topController = UIApplication.shared.keyWindow?.rootViewController
while (topController.presentedViewController != nil)
topController = topController.presentedViewController!
【讨论】:
【参考方案11】:此时,在您的代码中,仅创建了视图控制器的视图,但未将其添加到任何视图层次结构中。如果您想尽快从该视图控制器呈现,您应该在viewDidAppear
中进行,以确保最安全。
【讨论】:
如果我把它放在viewDidAppear中,那么当我关闭presentedViewController时,它会再次调用viewDidAppear方法并再次呈现viewController。我有一个在呈现之前放置条件语句的解决方法,但是有什么办法可以代替条件语句? 我会说,当屏幕出现时尝试呈现另一个模式是一种奇怪的行为,所以状态布尔并不是最糟糕的解决方案。同时,想想您需要显示模式的根本原因,看看您是否可以访问该信息。 如果在viewWillAppear中进行,开始演示时会出现正在演示中的情况。另一种方法是将其放在 viewWillAppear 中,但使用 ios 8 中的新transitionCoordinator 属性在过渡完成中添加代码。更多信息可以在这里找到developer.apple.com/library/prerelease/ios/documentation/UIKit/…【参考方案12】:斯威夫特 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)
【讨论】:
感谢@Jacob Davis!我用它来展示 alertController 因为我收到了警告:尝试展示...... 这非常有用。一些正在呈现控制器但屏幕没有出现的东西。突然它被解雇了。还有其他代码需要实现吗?请建议【参考方案13】:适用于 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
【讨论】:
【参考方案14】:斯威夫特 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
如果您需要在多个故事板屏幕之间切换,只需调整为视图控制器即可。
【讨论】:
【参考方案15】: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!
希望这可以帮助其他人使用 swift 3
【讨论】:
【参考方案16】:对于 SWIFT
func topMostController() -> UIViewController
var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
while (topController.presentedViewController != nil)
topController = topController.presentedViewController!
return topController
【讨论】:
谢谢!这是为我解决此错误的唯一方法。我试图在视图完全加载之后(在 Xcode 8 / iOS 10 中)从手势识别器触发的函数中呈现模态 VC。奇怪的是,这个函数返回的topController
与self
在尝试直接使用self.presentViewController(myModalVC)
呈现时完全相同的VC,但是当我使用你的函数传入呈现的VC时没有视图层次错误。跨度>
【参考方案17】:
在目标 c 中: 这解决了我在 mpmovieplayer 上展示 viewcontroller 时遇到的问题
- (UIViewController*) topMostController
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController)
topController = topController.presentedViewController;
return topController;
【讨论】:
以上是关于警告:尝试在其视图不在窗口层次结构中的 * 上呈现 * - swift的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin.Forms 警告:尝试使用 iOS 图像/手势识别器在其视图不在窗口层次结构中的 * 上呈现 *
尝试在其视图不在窗口层次结构中的 UIViewController 上呈现 UIViewController
尝试在其视图不在窗口层次结构中的 UIViewController 上呈现 UIViewController
尝试在其视图不在窗口层次结构中的 UIViewController 上呈现 UIViewController
尝试在其视图不在窗口层次结构中的 UIViewController 上呈现 UIViewController
警告:尝试在视图不在窗口层次结构中的 **.ViewController 上呈现 ZMNavigationController