如何判断completionHandler执行的队列?

时间:2018-02-23 16:09:53

标签: ios swift asynchronous grand-central-dispatch completionhandler

查看URLSession.dataTask的{​​{1}},很明显这个函数是异步调用的,但是没有提到completionHandler是否返回主线程,调用的线程它或者保留在执行dataTaskOperation的线程上。

这里有一个普遍的约定吗?

  let task = URLSession.shared().dataTask(with: request) {
        //What Thread are we on here?
    }

3 个答案:

答案 0 :(得分:3)

来自completionHandler的{​​{1}}参数的文档:

  

此处理程序在委托队列上执行。

所以下一个问题是,委托队列是什么?这一切都取决于URLSession dataTask的设置方式。您正在使用URLSession会话设置shared委托队列。 nil方法的queue参数的文档说明:

  

如果为nil,则会话创建一个串行操作队列,用于执行所有委托方法调用和完成处理程序调用。

因此,您发布的代码会导致在后台串行队列上调用完成处理程序。

答案 1 :(得分:1)

<强> URLSession

在文档中说......

  

此处理程序在委托队列上执行。

查看委托队列......

  

在此队列上执行与会话相关的所有委托方法调用和完成处理程序。会话对象保留对此队列的强引用,直到您的应用程序退出或取消分配会话对象。如果您没有使会话无效,那么您的应用程序会在内存泄漏之前泄漏内存。

     

请注意

     

此队列必须在创建对象时设置,并且不能更改。

查看init方法......

实际上并没有说明使用什么类型的队列......

嗯...

正如@rmaddy所指出的那样,会话会创建一个串行队列,以便在后台线程上运行。

<强>会展

至于公约......实际上没有。

如果您自己编写有需要考虑的事项......完成可能会更新UI吗?完成是否会进行大量的数据处理......您可以从那里做出决定。

答案 2 :(得分:0)

正如@rmaddy 所建议的,它确实在单独的队列中运行。它似乎被标记为:com.apple.NSURLSession-delegate

实验:

import Foundation

func currentQueueName() -> String? {
    String(cString: __dispatch_queue_get_label(nil), encoding: .utf8)
}

let dispatchQueue = DispatchQueue(label: "my-queue", qos: .userInteractive)
dispatchQueue.async {
    print(currentQueueName()!) // output: my-queue
    URLSession.shared.dataTask(with: URL(string:"https://www.google.com")!) { _,_,_ in
        print(currentQueueName()!) // output: com.apple.NSURLSession-delegate
    }.resume()
}