等待 session.dataTask 上的任务返回 [英] Wait for task return on session.dataTask

查看:81
本文介绍了等待 session.dataTask 上的任务返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目,用于从 API 发送和取回数据.发送和获取它工作正常.

I have a project where I send and get data back from an API. Sending and getting it works fine.

我的目标是等待来自服务器的响应(即:是|否),并根据它,继续与否,如果否,则显示警报.

My goal is to wait a response (ie: yes|no) from the server and depending on it, proceed with the segue or not and show an alert if no.

对于这部分,我有:

  1. 一个带有客户列表的表格视图和一个用于添加新客户的按钮.
  2. 我添加/编辑客户的详细视图
  3. 在详细视图上有一个保存按钮,其中包含一个转至 tableview 视图的 segue

函数saveClient()获取数据并向服务器发出请求

The function saveClient() gets the data and makes a request to the server

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

没有先生

是的

正确的应该是:

a1

是的

是的,先生

最后说明:

  1. 我尝试了一些使用信号量的例子......但没有奏效.

  1. I tried some examples w semaphores... but it didn't work.

我在其他地方使用了一个名为 meal 的 var 并且没有将它更改为客户端.但是,它不会干扰那部分代码

I'm using a var named meal on other places and haven't changed it to clients. However, it doesn't interfere on that part of the code

推荐答案

你说:

我的目标是等待来自服务器的响应(即:是|否),并根据它,继续与否

My goal is to wait a response (ie: yes|no) from the server and depending on it, proceed with the segue or not

虽然我理解这种方法的自然吸引力,但现实是您永远不应该等待"(尤其是在 shouldPerformSegue 中).您的 UI 将冻结(如果用户的 Internet 连接不佳,则尤其明显),您的应用很容易被寻找冻结应用的看门狗进程杀死等.

While I understand the natural appeal of that approach, the reality is that you never should "wait" (especially in shouldPerformSegue). Your UI will freeze (especially notable if the user has poor Internet connectivity), your app is susceptible to being killed by the watchdog process that looks for frozen apps, etc.

因此,与其执行 segue 并让 shouldPerformSegue 尝试等待网络响应以查看是否可以继续,不如反过来:您可以编写执行查询的代码如果一切正常,则只有以编程方式启动 segue.

So, rather than performing the segue and having shouldPerformSegue try to wait for the network response to see if it's OK to proceed, do it the other way around: You can write code that performs the query and if everything is good, only then initiate segue programmatically.

这篇关于等待 session.dataTask 上的任务返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆