【问题标题】:Swift 4 Attempt to present ViewController whose view is not in the window hierarchySwift 4 尝试呈现视图不在窗口层次结构中的 ViewController
【发布时间】:2019-06-10 02:36:54
【问题描述】:

我正在使用swift 4,当我在使用Firebase 注册用户时出现错误时,我正在尝试创建alertView。我有一个IBAction 用于注册按钮,它将使用来自两个textfields 的文本为用户注册,一个用于电子邮件,一个用于密码。

当注册过程出现错误时,我基本上试图显示alertview,例如有一个空的textfield

我已将功能的屏幕截图附加到发生该功能的位置。我知道我实际上遇到了一个错误,因为如果有一个错误,打印语句就会输出一个错误。

无论是否有错误,都不会显示警报视图,并且应用程序无论如何都会执行 segue。

2019-01-15 21:40:26.368924-0500 Pronto[9036:225268] 警告:尝试 呈现在 谁的观点不在 窗口层次结构

这是我现在显示的警报视图的输出。 我查看了所有其他关于同一问题的帖子,但似乎都没有。

【问题讨论】:

  • 寻找您的视图层次结构,注册屏幕模态呈现??
  • 尝试参考这个link,它可能会回答你的问题..

标签: ios swift firebase swift4 uialertview


【解决方案1】:

由于您的视图层次结构而发生此问题。

你需要找出你的 Current/Topmost 视图控制器是什么 查看层次结构并在其上显示您的警报。

要找出最顶层的视图控制器,请使用以下代码:

func getTopMostViewController() -> UIViewController? {
    var topMostViewController = UIApplication.shared.keyWindow?.rootViewController

    while let presentedViewController = topMostViewController?.presentedViewController {
        topMostViewController = presentedViewController
    }

    return topMostViewController
}

并在最顶层的视图控制器上显示您的警报并使用主线程来显示警报,因为闭包可能在另一个线程上工作。

DispatchQueue.main.async { 
    getTopMostViewController()?.present(alertController, animated: true, completion: nil)
}

请参考这个堆栈答案: Swift 3 Attempt to present whose view is not in the window hierarchy

【讨论】:

  • 感谢您的回答,这似乎有助于我显示警报视图。但是,在我转到屏幕后会显示警报视图。如果出现警报,我需要它不要继续
  • @SteveSahayadarlin 很高兴听到这个消息,如果最顶层的视图控制器是 AlertViewController 的类型,您可以停止执行 segue。您只需要添加一张支票。
  • 我基本上做了什么,我删除了故事板中的 segue,然后调用了一个 present 函数并以编程方式进行了 segue,现在一切正常。谢谢
  • DispatchQueue.main.async 是关键兄弟!真棒答案!为我节省了很多时间。非常感谢!
  • 这解决了我试图从自定义类中更改情节提要的很多头痛问题。伟大的工作。
【解决方案2】:

尝试使用 ViewDidAppear 代替 View did Load。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let alertViewController = UIAlertController(title: "Any", message: "Any Custom Message", preferredStyle: .alert)

    alertController.addAction(UIAlertAction(title: "ANy", style: .cancel, handler: nil))
    present(alertViewController, animated: true, completion: nil)
}

【讨论】:

  • 他正在使用来自 @IBAction 的 API 回调,所以这不是问题
【解决方案3】:

您可以获得最顶层的视图控制器并让该视图控制器显示警报。所以不要使用self.present,而是使用这种方法,看看它是否有效:

let topViewController = UIApplication.shared.keyWindow?.rootViewController
topViewController?.present(alertController, animated: true, completion: nil)

也尝试在主线程上显示,因为您试图在 createUser 完成处理程序中显示警报:

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

【讨论】:

  • 刚刚试过这个,但它仍然给我同样的问题,视图不在层次结构中
  • @SteveSahayadarlin 好的,你试过在主线程上演示吗?
  • 不确定您的意思,您能否澄清或详细说明?
  • 在另一篇文章中发现了这一点,但为了确定,再试一次,就像您更新的答案一样。不幸的是,同样的问题
  • @SteveSahayadarlin 你试过showMessagePrompt吗?检查此链接 firebase.google.com/docs/auth/ios/email-link-auth 它与 firebase 中实现的 alertConroller 相同。
【解决方案4】:

检查您是否有“双击”问题:

  1. 你不小心双击了按钮
  2. signUpBtnPressed 被调用两次
  3. 第一个请求正确执行,从而启动segue,错误为nil
  4. 第二个请求返回类似“用户已存在”的错误,然后尝试显示来自当前控制器的警报,但 segue 已经启动并且下一个控制器已经出现

通过使用带有 UI 阻塞的加载器(例如 SVProgressHUD)来解决此问题 - 在方法的开头启动加载器并在回调中将其关闭。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-23
    • 2015-09-17
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    相关资源
    最近更新 更多