尝试呈现其视图不在窗口层次结构中的 UIAlertController (Swift 3/Xcode 8)
Posted
技术标签:
【中文标题】尝试呈现其视图不在窗口层次结构中的 UIAlertController (Swift 3/Xcode 8)【英文标题】:Attempt to present UIAlertController whose view is not in the window hierarchy (Swift 3/Xcode 8) 【发布时间】:2017-09-10 14:39:30 【问题描述】:我正在尝试创建一个应用程序,并且我想在出现登录错误或用户忘记输入用户名和/或密码时显示警报。但是,我总是收到此警告:
警告:尝试在 谁的视野不在窗内 等级制度!
我已经尝试了在这里找到的其他解决方案,但我仍然无法修复它。这是我的代码:
func createAlert(title: String, message: String)
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: (action) in
self.dismiss(animated: true, completion: nil)
))
self.present(alert, animated: true, completion: nil)
@IBAction func signInPressed(_ sender: Any)
if usernameTextField.text == "" || passwordTextField.text == ""
createAlert(title: "Error in form", message: "Please enter an email and password.")
else
var activityIndicator = UIActivityIndicatorView()
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndicator.center = self.view.center
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents()
PFUser.logInWithUsername(inBackground: usernameTextField.text!, password: passwordTextField.text!, block: (user, error) in
activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
if error != nil
var displayErrorMessage = "Please try again later."
let error = error as NSError?
if let errorMessage = error?.userInfo["error"] as? String
displayErrorMessage = errorMessage
self.createAlert(title: "Sign in error", message: displayErrorMessage)
else
print("Logged in")
self.performSegue(withIdentifier: "toSignIn", sender: self)
)
更新:这是整个视图控制器
class ViewController: UIViewController
@IBOutlet var usernameTextField: UITextField!
@IBOutlet var passwordTextField: UITextField!
func createAlert(title: String, message: String)
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: (action) in
self.dismiss(animated: true, completion: nil)
))
self.present(alert, animated: true, completion: nil)
@IBAction func signInPressed(_ sender: Any)
if usernameTextField.text == "" || passwordTextField.text == ""
createAlert(title: "Error in form", message: "Please enter an email and password.")
else
var activityIndicator = UIActivityIndicatorView()
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndicator.center = self.view.center
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents()
PFUser.logInWithUsername(inBackground: usernameTextField.text!, password: passwordTextField.text!, block: (user, error) in
activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
if error != nil
var displayErrorMessage = "Please try again later."
let error = error as NSError?
if let errorMessage = error?.userInfo["error"] as? String
displayErrorMessage = errorMessage
self.createAlert(title: "Sign in error", message: displayErrorMessage)
else
print("Logged in")
self.performSegue(withIdentifier: "toSignIn", sender: self)
)
override func viewDidAppear(_ animated: Bool)
if PFUser.current() != nil
performSegue(withIdentifier: "toSignIn", sender: self)
self.tabBarController?.tabBar.isHidden = true
override func viewDidLoad()
super.viewDidLoad()
【问题讨论】:
您可能在viewDidLoad
或其他地方调用createAlert
。您能否添加您的整个视图控制器代码?
@PranavKasetti 我已经用整个视图控制器代码更新了我的帖子
好的。您使用 segue 导航到哪个视图控制器?
@PranavKasetti 到标签栏控制器视图
为什么self.dismiss(animated: true, completion: nil)
在你的UIAlertAction
的完成处理程序中?如果您将完成处理程序声明为 nil
和 self
是指在此上下文中显示警报的视图控制器,则警报会自动解除,因此您不会像那样解除警报。
【参考方案1】:
首先创建UIAlertController这样一个属性。
var alertController: UIAlertController?
您必须像这样在 viewDidLoad() 中添加它:
override func viewDidLoad()
super.viewDidLoad()
self.alertController = UIAlertController(title: "Alert", message: "Not images yet", preferredStyle: .alert)
self.alertController?.addAction(UIAlertAction(title: "Close", style: .default))
view.addSubview((alertController?.view)!)
因此,当您按下 signInButton 并且登录不正确时,您必须调用。
@IBAction func signInPressed(_ sender: Any)
if usernameTextField.text == "" || passwordTextField.text == ""
createAlert(title: "Error in form", message: "Please enter an email and password.")
else
var activityIndicator = UIActivityIndicatorView()
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndicator.center = self.view.center
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents()
PFUser.logInWithUsername(inBackground: usernameTextField.text!, password: passwordTextField.text!, block: (user, error) in
activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
if error != nil
self.presentedViewController?.present(self.alertController!, animated: true, completion: nil)
【讨论】:
【参考方案2】:每当我们试图在任何闭包中呈现 UIAlertController 时,我们都应该在主线程上调用它,例如:
DispatchQueue.main.async [weak self] in
self?.createAlert(title: "Sign in error", message: displayErrorMessage)
【讨论】:
【参考方案3】:为 Swift 3
试试这个代码func displayMyAlertMessageError(userMessage:String, titleHead: String)
//define displyMyAlertMessage.
let MyAlert = UIAlertController(title: titleHead, message: userMessage, preferredStyle:UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title: "Okay", style: UIAlertActionStyle.default, handler: nil);MyAlert.addAction(okAction);
self.present(MyAlert,animated:true,completion:nil);
@IBAction func signInPressed(_ sender: Any)
if (usernameTextField.text?.isEmpty) || (passwordTextField.text?.isEmpty)
createAlert(title: "Error in form", message: "Please enter an email and password.")
else
//Your code here
【讨论】:
【参考方案4】:将您的 createAlert 方法更改为此,
func createAlert(title: String, message: String, controller: UIViewController)
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: (action) in
self.dismiss(animated: true, completion: nil)
))
controller.present(alert, animated: true, completion: nil)
然后像这样创建警报,
self.createAlert(title: "Sign in error", message: "Please try again later.", controller: self)
这可能会解决您的问题。
【讨论】:
谢谢!但它仍然在我的调试区域显示相同的警告:(以上是关于尝试呈现其视图不在窗口层次结构中的 UIAlertController (Swift 3/Xcode 8)的主要内容,如果未能解决你的问题,请参考以下文章
尝试在其视图不在窗口层次结构中的 UIViewController 上呈现 UIViewController
尝试在其视图不在窗口层次结构中的 UIViewController 上呈现 UIViewController
尝试在其视图不在窗口层次结构中的 UIViewController 上呈现 UIViewController
尝试呈现其视图不在窗口层次结构中的 UIAlertController (Swift 3/Xcode 8)
警告:尝试在其视图不在窗口层次结构中的 ViewController 上呈现 ViewController (w/UIAlertController)