等待session.dataTask

时间:2018-01-04 17:35:55

标签: ios swift task nsurlsession

我有一个项目,我从API发送并获取数据。发送和获取它可以正常工作。

我的目标是等待来自服务器的响应(即:是|否),并根据它,继续或不进行segue,如果没有则显示警告。

对于这部分我有:

  1. 包含客户列表和添加新客户端按钮的tableview视图。
  2. 我添加/编辑客户端的详细信息视图
  3. 在详细视图上有一个保存按钮,其中有一个segue到tableview视图
  4. 函数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

         

    不,先生

         

    正确的是:

      

    A1

         

         

    是的,先生

    最后的说明:

    1. 我尝试了一些信号量示例......但它没有用。

    2. 我在其他地方使用var命名餐,并没有将其改为客户。但是,它不会干扰代码的那部分

1 个答案:

答案 0 :(得分:0)

你说:

  

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

虽然我理解这种方法的自然吸引力,但现实是你永远不应该等待&#34; (特别是在shouldPerformSegue)。您的用户界面将冻结(如果用户的互联网连接较差,尤其值得注意),您的应用程序很容易被寻找冻结应用程序等的监视程序进程杀死。

因此,不是执行segue并让shouldPerformSegue尝试等待网络响应以查看是否可以继续,而是反过来:您可以编写执行查询,如果一切都很好,只有以编程方式启动segue。