如何判断 completionHandler 在哪个队列上执行?

How to tell what queue a completionHandler executes on?

查看 documentationURLSession.dataTask 很明显这个函数是异步调用的,但是没有提到 completionHandler returns 到主线程,调用它的线程还是保留在执行 dataTaskOperation 的线程上。

这里有一个通用的约定吗?

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

URLSession

文档中说...

This handler is executed on the delegate queue.

并查看委托队列...

All delegate method calls and completion handlers related to the session are performed on this queue. The session object keeps a strong reference to this queue until your app exits or the session object is deallocated. If you do not invalidate the session, your app leaks memory until it exits.

Note

This queue must be set at object creation time and may not be changed.

并查看 init 方法...

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

嗯...

正如@rmaddy 所指出的,会话创建了一个串行队列,因此 运行 在后台线程上。

约定

至于约定……真的没有。

如果您自己编写,则需要考虑一些事项...完成后是否可能会更新 UI?完成是否会进行大量数据处理等...您可以从那里决定。

来自URLSession dataTaskcompletionHandler参数的文档:

This handler is executed on the delegate queue.

那么下一个问题是,什么是委托队列?这完全取决于 URLSession 的设置方式。您正在使用设置 nil 委托队列的 shared 会话。 init 方法的 queue 参数的文档指出:

If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.

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

正如@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()
}