我目前正在使用Swift 3开发IOS应用程序。我正在使用登录系统。登录验证工作正常。逻辑是,如果登录成功,它将进入下一个屏幕。但是,如果用户不存在,则应显示UIAlert的错误消息。但是当我尝试显示UIAlert时,我收到一条错误,上面写着"断言失败 - [UIKeyboardTaskQueue waitUntilAllTasksAreFinished]"
//Getting data from database
func getData() -> Void {
let url: String = "http://localhost/fridge_app/login.php" //this will be changed to the path where service.php lives
//created NSURL
let requestURL = NSURL(string: url)
//creating NSMutableURLRequest
var request = URLRequest(url: requestURL! as URL)
//setting the method to post
request.httpMethod = "POST"
//Getting values from textfield
let usernameVal = username.text
let passwordVal = password.text
//creating the post parameter by concatenating the keys and values from text field
let postString = "username=\(usernameVal!)&password=\(passwordVal!)";
print(postString)
request.httpBody = postString.data(using: String.Encoding.utf8)
//creating a task to send the post request
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
//exiting if there is some error
if error != nil{
print("error is \(error)")
return;
}
// Print out response string
var responseString: NSString?;
responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
if(responseString == "invalid"){
self.isValid = false;
print(self.isValid)
}
if self.checkLogin(data: responseString!) == true {
self.performSegue(withIdentifier: "profileViewController", sender: self)
}
else{
print("Hello")
// It prints hello fine, but when it tries to run the showAlert function it fails
self.showAlert()
}
//print("responseString = \(self.responseString)")
}
//executing the task
task.resume()
}
这是警报功能
/*
* Show UIAlert Message
*/
func showAlert() -> Void{
let alert = UIAlertController(title: "User Does Not Exist",
message: "",
preferredStyle: UIAlertControllerStyle.alert)
let loginFail = UIAlertAction(title: "Close", style: .default, handler: nil);
alert.addAction(loginFail);
present(alert, animated: true)
}
当用户单击登录时调用此方法。
答案 0 :(得分:3)
除非您采取特殊步骤,否则您提交给NSURLSession的任务的完成处理程序将在后台线程上运行。这意味着您所做的任何UI调用都必须发送到主线程,否则他们无法正常工作(并可能导致您的应用崩溃。)
完成处理程序中的代码执行的UI工作比调用警报要多。你也在调用一个segue。如果你的完成处理程序没有做很费时间的工作,你可能想要将整个事情包装在对主线程的GCD调用中:
DispatchQueue.main.async() {
//Put the entire body of your completion handler in here
}
否则,您需要在如上所述的主队列调用中单独包装每个UI调用。
查看您的特定完成处理程序,您有一个if / then / else块执行UIKit调用:
if self.checkLogin(data: responseString!) {
self.performSegue(withIdentifier: "profileViewController",
sender: self)
} else {
print("Hello")
self.showAlert()
}
所以只需将该部分包装在对主队列的调用中:
DispatchQueue.main.async() {
if self.checkLogin(data: responseString!) {
self.performSegue(withIdentifier: "profileViewController",
sender: self)
} else {
print("Hello")
self.showAlert()
}
}