Swift 3.0中的完成处理程序

时间:2017-01-19 15:16:02

标签: swift3

我正在使用以下代码与我的服务器同步数据。完成任务后,我想打电话:

self.refreshControl?.endRefreshing()

但是,我想确保它发生在此方法中可能发生的任何事情之后。这是我要使用完成处理程序的地方吗?这让我感到困惑,因为我已经运行了在获得http响应后执行的代码。如果我添加一个完成处理程序,它会在收到http响应后执行吗?我可以将我的endRefreshing()代码放在那里,这可能发生在下面的代码中可能发生的任何事情之后吗? 谢谢!

func syncCustomers(token: String) {
    let url:NSURL = NSURL(string: Constants.Api.BaseUrl + "api/customer")!
    let session = URLSession.shared
    let request = NSMutableURLRequest(url: url as URL)
    request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
    request.httpMethod = "GET"
    let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
        guard let data = data else { return }
        do {
            if error != nil {
                self.showAlert(title: "Error", message: error!.localizedDescription)
            }
            else if let httpResponse = response as? HTTPURLResponse {
                if httpResponse.statusCode == 200 {
                    let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? Array<Any>
                    DispatchQueue.global().async {
                        for item in json! {
                            if let customer = Customer(json: item as! [String : Any]) {
                                _ = SqliteDB.instance.replaceCustomer(customer: customer)
                            }
                        }
                        self.customers = SqliteDB.instance.getCustomers()
                        self.tableView.reloadData()
                    }
                } else if httpResponse.statusCode == 401 {
                    self.showAlert(title: "Error", message: "Unauthorized. Please try logging in again.")

                }
            }
        } catch let error as NSError {
            self.showAlert(title: "Error", message: error.localizedDescription)
        }
    }
    task.resume()
}

2 个答案:

答案 0 :(得分:24)

完成或关闭只是一个包含在参数中的函数......

您可以创建一个具有闭包功能的函数......

func doSomethingAsync(completion: () -> ()) {
}

参数completion的类型为() -> (),它是......函数->,不带输入参数()并返回void ()

您还可以制作类似......的功能。

// (inputs) -> (outputs)
(String) -> ()

或者您想要的任何输入或输出。

现在,就像你的问题一样。此函数可能会调用其他异步函数...

func myAsyncFunction(completion: () -> ()) {

    someOtherAsyncFunction() {

        // This is the completion of "someOtherAsyncFunction"

        // Call YOUR completion here...
        completion()
    }

}

要确保在完成其他异步方法后调用完成,请将其置于另一个方法的完成之内。像上面一样。

现在,打电话给你,你可以做...

self.myAsyncFunction() {
    // your completion block code here.
}

现在,在其他异步方法完成后,将调用完成块代码。

当然,如果你在另一个完成中有多条路径(比如错误等等),那么你必须在每个终点调用你的完成...

func myAsyncFunction(completion: () -> ()) {

    someOtherAsyncFunctionWithAPossibleError() {
        error in

        if error != nil {
            completion()
            // this return means the other completion won't be run
            return
        }

        completion()
    }

}

答案 1 :(得分:11)

Swift 4:

  1. 创建一个完成块。

    func getDataFromJson(url: String, parameter: String, completion: @escaping (_ success: [String : AnyObject]) -> Void) {
    
        //@escaping...If a closure is passed as an argument to a function and it is invoked after the function returns, the closure is @escaping.
    
        var request = URLRequest(url: URL(string: url)!)
        request.httpMethod = "POST"
        let postString = parameter
    
        request.httpBody = postString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) { Data, response, error in
    
            guard let data = Data, error == nil else {  // check for fundamental networking error
    
                print("error=\(error)")
                return
            }
    
            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {  // check for http errors
    
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print(response!)
                return
    
            }
    
            let responseString  = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String : AnyObject]
            completion(responseString)
    
    
    
        }
        task.resume()
    }
    
  2. 通话方法

    getDataFromJson(url: "http://www.windmillinfotech.com/carlife/carlife_api/automotive_product_list", parameter: "vehicle_type=Car", completion: { response in
            print(response)
    
        })