使用Swift 4,我有这个代码尝试对REST API发出POST请求:
spinner.startAnimation(self)
btnOk.isEnabled = false
btnCancel.isEnabled = false
attemptPost()
spinner.stopAnimation(self)
btnOk.isEnabled = true
btnCancel.isEnabled = true
执行此操作的函数(Constants
和Request
是我创建的用于创建请求对象并保存常用数据的类:
func attemptPost() {
let url = Constants.SERVICE_URL + "account/post"
let body: [String : Any] =
["firstName": txtFirstName.stringValue,
"lastName": txtLastName.stringValue,
"email": txtEmail.stringValue,
"password": txtPassword.stringValue];
let req = Request.create(urlExtension: url, httpVerb: Constants.HTTP_POST, jsonBody: body)
let task = URLSession.shared.dataTask(with: req) { data, response, err in
guard let data = data, err == nil else {
// error
return
}
if let resp = try? JSONSerialization.jsonObject(with: data) {
// success
}
}
task.resume()
}
由于执行此操作的任务以异步方式运行,因此一旦调用attemptPost()
返回,就无法按顺序更新UI。由于UI组件位于主线程上,因此无法直接更新发出请求的任务中的组件。
在C#中,它的工作方式相同;有一个BackgroundWorker
类,您可以在其中安全地更新UI组件,以避免“跨线程操作无效”错误。
我正在尝试找到一个或多或少完成同样事情的示例,其中建立“等待”状态,任务运行,并且在任务完成时,主线程被通知任务已完成,等待状态可以改变。
但是我仍然无法理解Swift中这一切是如何结合在一起的。我环顾四周,看到了有关从URLSessionDataTask
内部调用的处理程序的信息以及有关GCD的信息,但我仍然无法连接点。
GCD在这里甚至是相关的,因为URLSessionDataTask
任务是异步开始的吗?
感谢任何帮助。
答案 0 :(得分:3)
如果我理解正确,你可以尝试这个解决方案:
spinner.startAnimation(self)
btnOk.isEnabled = false
btnCancel.isEnabled = false
attemptPost { (success) in
DispatchQueue.main.async {
spinner.stopAnimation(self)
btnOk.isEnabled = true
btnCancel.isEnabled = true
}
// UI wise, eventually you can do something with 'success'
}
func attemptPost(_ completion:@escaping (Bool)->())
let url = Constants.SERVICE_URL + "account/post"
let body: [String : Any] =
["firstName": txtFirstName.stringValue,
"lastName": txtLastName.stringValue,
"email": txtEmail.stringValue,
"password": txtPassword.stringValue];
let req = Request.create(urlExtension: url, httpVerb: Constants.HTTP_POST, jsonBody: body)
let task = URLSession.shared.dataTask(with: req) { data, response, err in
guard let data = data, err == nil else {
completion(false)
return
}
if let resp = try? JSONSerialization.jsonObject(with: data) {
completion(true)
}
}
task.resume()
}
所以这个想法是从attemptPost
执行一个块,它将异步运行到主线程你的UI东西