等待 session.dataTask 上的任务 return
Wait for task return on session.dataTask
我有一个项目,我从 API 发送数据并从中获取数据。发送和接收都正常。
我的目标是等待来自服务器的响应(即:是|否),并根据它,是否继续进行 segue,如果没有则显示警报。
对于这部分我有:
- 带有客户列表和添加新客户按钮的表视图。
- 我 add/edit 一个客户的详细视图
- 在详细视图上有一个保存按钮,带有到表视图视图的 segue
函数saveClient()
获取数据并向服务器发出请求
func saveClient() -> Bool {
let name = txtName.text ?? ""
let address = txtAddress.text ?? ""
let city = txtCity.text ?? ""
let province = txtProvince.text ?? ""
let postal_code = txtPostalCode.text ?? ""
meal = Client(name:name, client_id: "", postal_code: postal_code, province: province, city: city, address: address)
var jsonData = Data()
let jsonEncoder = JSONEncoder()
do {
jsonData = try jsonEncoder.encode(meal)
}
catch {
}
print("a1")
var success: Bool
success = false
makeRequestPost(endpoint: "http://blog.local:4711/api/clients/add",
requestType: "POST",
requestBody: jsonData,
completionHandler: { (response : ApiContainer<Client>?, error : Error?) in
if let error = error {
print("error calling POST on /todos")
print(error)
return
}
let b = (response?.meta)!
print(b.sucess)
if(b.sucess == "yes") {
success = true
}
else
{
DispatchQueue.main.async(execute: {
let myAlert = UIAlertController(title: "Error", message: "Error creating Client", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil)
myAlert.addAction(okAction)
self.present(myAlert, animated: true, completion: nil)
})
return
}
} )
return success
}
在同一个控制器上:
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
guard let button = sender as? UIBarButtonItem, button === btnSave else {
return false
}
if !saveClient() {
print("no sir")
return false
}
print("yes sir")
return true
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
guard let button = sender as? UIBarButtonItem, button === btnSave else {
return
}
}
请求函数:
func makeRequestPost<T>(endpoint: String,
requestType: String = "GET",
requestBody: Data, completionHandler: @escaping (ApiContainer<T>?, Error?) -> ()) {
guard let url = URL(string: endpoint) else {
print("Error: cannot create URL")
let error = BackendError.urlError(reason: "Could not create URL")
completionHandler(nil, error)
return
}
var urlRequest = URLRequest(url: url)
let session = URLSession.shared
urlRequest.httpMethod = "POST"
urlRequest.httpBody = requestBody
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: urlRequest, completionHandler: {
(data, response, error) in
guard let responseData = data else {
print("Error: did not receive data")
completionHandler(nil, error)
return
}
guard error == nil else {
completionHandler(nil, error!)
return
}
do {
let response = try JSONDecoder().decode(ApiContainer<T>.self, from: responseData)
completionHandler(response, nil)
}
catch {
print("error trying to convert data to JSON")
print(error)
completionHandler(nil, error)
}
})
task.resume()
}
在控制台上我得到:
a1
no sir
yes
正确的是:
a1
yes
yes sir
最后的笔记:
我尝试了一些带有信号量的示例...但它没有用。
我在其他地方用的是一个名为 meal 的 var,还没有改成 clients。但是,它不会干扰那部分代码
你说:
My goal is to wait a response (ie: yes|no) from the server and depending on it, proceed with the segue or not
虽然我理解这种方法的自然吸引力,但现实是您永远不应该 "wait"(尤其是在 shouldPerformSegue
中)。您的 UI 将冻结(如果用户的 Internet 连接不佳,尤其值得注意),您的应用程序很容易被寻找冻结应用程序的看门狗进程杀死,等等。
因此,与其执行 segue 并让 shouldPerformSegue
尝试等待网络响应以查看是否可以继续,不如以相反的方式进行:您可以编写执行查询的代码,然后如果一切都很好,然后才以编程方式启动 segue。
我有一个项目,我从 API 发送数据并从中获取数据。发送和接收都正常。
我的目标是等待来自服务器的响应(即:是|否),并根据它,是否继续进行 segue,如果没有则显示警报。
对于这部分我有:
- 带有客户列表和添加新客户按钮的表视图。
- 我 add/edit 一个客户的详细视图
- 在详细视图上有一个保存按钮,带有到表视图视图的 segue
函数saveClient()
获取数据并向服务器发出请求
func saveClient() -> Bool {
let name = txtName.text ?? ""
let address = txtAddress.text ?? ""
let city = txtCity.text ?? ""
let province = txtProvince.text ?? ""
let postal_code = txtPostalCode.text ?? ""
meal = Client(name:name, client_id: "", postal_code: postal_code, province: province, city: city, address: address)
var jsonData = Data()
let jsonEncoder = JSONEncoder()
do {
jsonData = try jsonEncoder.encode(meal)
}
catch {
}
print("a1")
var success: Bool
success = false
makeRequestPost(endpoint: "http://blog.local:4711/api/clients/add",
requestType: "POST",
requestBody: jsonData,
completionHandler: { (response : ApiContainer<Client>?, error : Error?) in
if let error = error {
print("error calling POST on /todos")
print(error)
return
}
let b = (response?.meta)!
print(b.sucess)
if(b.sucess == "yes") {
success = true
}
else
{
DispatchQueue.main.async(execute: {
let myAlert = UIAlertController(title: "Error", message: "Error creating Client", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil)
myAlert.addAction(okAction)
self.present(myAlert, animated: true, completion: nil)
})
return
}
} )
return success
}
在同一个控制器上:
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
guard let button = sender as? UIBarButtonItem, button === btnSave else {
return false
}
if !saveClient() {
print("no sir")
return false
}
print("yes sir")
return true
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
guard let button = sender as? UIBarButtonItem, button === btnSave else {
return
}
}
请求函数:
func makeRequestPost<T>(endpoint: String,
requestType: String = "GET",
requestBody: Data, completionHandler: @escaping (ApiContainer<T>?, Error?) -> ()) {
guard let url = URL(string: endpoint) else {
print("Error: cannot create URL")
let error = BackendError.urlError(reason: "Could not create URL")
completionHandler(nil, error)
return
}
var urlRequest = URLRequest(url: url)
let session = URLSession.shared
urlRequest.httpMethod = "POST"
urlRequest.httpBody = requestBody
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: urlRequest, completionHandler: {
(data, response, error) in
guard let responseData = data else {
print("Error: did not receive data")
completionHandler(nil, error)
return
}
guard error == nil else {
completionHandler(nil, error!)
return
}
do {
let response = try JSONDecoder().decode(ApiContainer<T>.self, from: responseData)
completionHandler(response, nil)
}
catch {
print("error trying to convert data to JSON")
print(error)
completionHandler(nil, error)
}
})
task.resume()
}
在控制台上我得到:
a1
no sir
yes
正确的是:
a1
yes
yes sir
最后的笔记:
我尝试了一些带有信号量的示例...但它没有用。
我在其他地方用的是一个名为 meal 的 var,还没有改成 clients。但是,它不会干扰那部分代码
你说:
My goal is to wait a response (ie: yes|no) from the server and depending on it, proceed with the segue or not
虽然我理解这种方法的自然吸引力,但现实是您永远不应该 "wait"(尤其是在 shouldPerformSegue
中)。您的 UI 将冻结(如果用户的 Internet 连接不佳,尤其值得注意),您的应用程序很容易被寻找冻结应用程序的看门狗进程杀死,等等。
因此,与其执行 segue 并让 shouldPerformSegue
尝试等待网络响应以查看是否可以继续,不如以相反的方式进行:您可以编写执行查询的代码,然后如果一切都很好,然后才以编程方式启动 segue。