Swift 4 尝试显示视图不在 window 层次结构中的 ViewController
Swift 4 Attempt to present ViewController whose view is not in the window hierarchy
我正在使用 swift 4
并尝试创建 alertView
,但在使用 Firebase
注册用户时出现错误。我有一个 IBAction
用于注册按钮,它将使用来自两个 textfields
的文本对用户进行注册,一个用于电子邮件,一个用于密码。
我基本上是在注册过程出现错误时尝试显示 alertview
,例如 textfield
.
为空
我已将函数的屏幕截图附加到发生的位置。我知道我实际上遇到了一个错误,因为如果有错误,print 语句会输出一个错误。
无论是否有错误,都不会显示警报视图,并且应用程序会执行 segue。
2019-01-15 21:40:26.368924-0500 Pronto[9036:225268] Warning: Attempt
to present on
whose view is not in the
window hierarchy
这是我为现在显示的警报视图获得的输出。
我查看了所有其他关于同一问题的帖子,但 none 似乎有效。
您可以获得最顶层的视图控制器并让该视图控制器显示警报。因此,不要使用 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)
}
检查您是否有 "double tap" 问题:
- 您不小心双击了按钮
signUpBtnPressed
被调用了两次
- 第一个请求正确执行,从而启动segue,错误为nil
- 第二个请求 returns 错误 'user already exists',然后尝试显示来自当前控制器的警报,但是 segue 已经启动并且下一个控制器已经出现
这已通过使用带 UI 阻塞的加载器解决(例如 SVProgressHUD)- 在方法开始时启动加载器并在回调中关闭它。
尝试使用 ViewDidAppear
而不是 View 来加载。
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)
}
此问题是由于您的视图层次结构所致。
You need to find out what is your Current/Topmost view controller in
view hierarchy and present your alert over it.
要找出最顶层的视图控制器,请使用以下代码:
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 4
并尝试创建 alertView
,但在使用 Firebase
注册用户时出现错误。我有一个 IBAction
用于注册按钮,它将使用来自两个 textfields
的文本对用户进行注册,一个用于电子邮件,一个用于密码。
我基本上是在注册过程出现错误时尝试显示 alertview
,例如 textfield
.
我已将函数的屏幕截图附加到发生的位置。我知道我实际上遇到了一个错误,因为如果有错误,print 语句会输出一个错误。
无论是否有错误,都不会显示警报视图,并且应用程序会执行 segue。
2019-01-15 21:40:26.368924-0500 Pronto[9036:225268] Warning: Attempt to present on whose view is not in the window hierarchy
这是我为现在显示的警报视图获得的输出。 我查看了所有其他关于同一问题的帖子,但 none 似乎有效。
您可以获得最顶层的视图控制器并让该视图控制器显示警报。因此,不要使用 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)
}
检查您是否有 "double tap" 问题:
- 您不小心双击了按钮
signUpBtnPressed
被调用了两次- 第一个请求正确执行,从而启动segue,错误为nil
- 第二个请求 returns 错误 'user already exists',然后尝试显示来自当前控制器的警报,但是 segue 已经启动并且下一个控制器已经出现
这已通过使用带 UI 阻塞的加载器解决(例如 SVProgressHUD)- 在方法开始时启动加载器并在回调中关闭它。
尝试使用 ViewDidAppear
而不是 View 来加载。
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)
}
此问题是由于您的视图层次结构所致。
You need to find out what is your Current/Topmost view controller in view hierarchy and present your alert over it.
要找出最顶层的视图控制器,请使用以下代码:
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)
}
请参考堆栈答案: