将完成处理程序与 DispatchQueue 一起使用

mod*_*ler 1 concurrency grand-central-dispatch completionhandler nsurlsession swift

我了解到并发DispatchQueue允许其中的代码立即返回,因此不会阻塞调用线程。这通常与加载大数据的后台任务一起使用。

我还了解到完成处理程序(例如, in URLSession)允许在某些任务完成后执行处理程序中的代码。

我的问题是:这是否意味着并发调度队列和完成处理程序具有重叠的目的?如果我已经使用了完成处理程序,就不需要用并发调度队列包装它吗?

比如下面是一个使用 URLSession 的耗时的数据加载任务,用并发调度队列包装它是不是一个好主意?

URLSession(configuration: URLSessionConfiguration.default).dataTask(with: propertiesRequest) { data, response, error in
        // print("within dataTask: data: \(data), response: \(response), error: \(error)")
        if let error = error {
            print(error)
        } else if let httpResponse = response as? HTTPURLResponse {
            if httpResponse.statusCode == 200 {
                print("success: property task request")


                do {

                    handler(responseDict, nil) // This is a function supplied by caller

                } catch let error as NSError {
                    handler(nil, error)
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 5

您不必将 Grand Central Dispatch (GCD) 调度队列与耗时的URLSession请求结合使用。

如果出现以下情况,您可能会在dataTask完成处理程序闭包中使用 GCD :

  1. 如果你在闭包内部做一些事情,它本身就是非常耗时的(例如处理非常复杂的请求),并且你不想占用URLSession用于处理其完成处理程序(和委托方法)的串行操作队列。这似乎不是这里的问题(例如,解析 JSON 响应通常足够快,我们不必担心这一点),但仅供参考。或者,

  2. 如果,当您完成对 的响应的解析后dataTask,如果您想更新某个模型对象或更新 UI。你想在主队列上做那些。

    例如,如果您的请求返回一堆对象以显示在某个 tableview 中,则您会将模型和 UI 的更新分派到主队列:

    DispatchQueue.main.async {
        self.objects = ...
        self.tableView.reloadData()
    }
    
    Run Code Online (Sandbox Code Playgroud)

但是您不必担心耗时的URLSession请求本身。这已经是异步发生的,因此您不必将其分派到后台队列。