在CS193P上,斯坦福大学讲课的讲师在第8讲中提到了多线程,我们在多线程中提到你为异步调用提供的闭包“没有参数,也没有返回任何参数”。这让我感到惊讶,因为不久之后他给出了一个iOS方法的例子(37:01),其中闭包能够返回参数,即:
let task = session.dataTask(with: url) { (data: Data?, response, error ) in ...
还有许多其他iOS方法似乎返回完成闭包的参数。我在这里错过了什么吗?为什么不能通过异步调用提供的闭包以与上面的dataTask调用类似的方式返回参数。
答案 0 :(得分:2)
dataTask(with:)
与DispatchQueue
' s async
不同。
首先,请记住您正在使用trailing closure。当函数的最后一个参数是一个闭包(即代码的"块")时,闭包可以放在括号之外。以下代码使用尾随闭包语法:
someQueue.async {
//do something
}
等同于以下代码,它不使用尾随闭包语法。:
someQueue.async(execute: {
//do something
})
另外,请记住,闭包不会"返回"参数,他们接受参数。参数是闭包的输入,而返回值是闭包的输出。
The function signature for DispatchQueue
's async
is:
func async(
group: DispatchGroup? = default,
qos: DispatchQoS = default,
flags: DispatchWorkItemFlags = default,
execute work: @escaping () -> Void
)
group
,qos
和flags
都有默认值,因此可以在此处忽略它们。重要的部分是execute
参数,其类型为@escaping () -> Void
。这意味着"一个不带参数的闭包并返回Void
(即没有值)。"
The function signature for URLSession's
dataTask
method is:
func dataTask(
with request: URLRequest,
completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void
) -> URLSessionDataTask
completionHandler
属于@escaping (Data?, URLResponse?, Error?) -> Void
类型,这意味着它接受三个参数(可选Data
,可选URLResponse
和可选Error
)和返回Void
。
两个函数都接受闭包作为参数,但它们接受具有不同签名的闭包。 async
接受一个不接受任何参数的闭包,但dataTask
接受一个接受三个参数的闭包。什么都没有"魔术"关于这些功能之一;他们只是接受闭包,如果你愿意,你可以编写自己的函数来接受闭包。
答案 1 :(得分:0)
并非所有异步API都使用多线程。在线程之间更新/传输数据时,内存管理还有其他注意事项。讲师的陈述可能是在多线程API的特定上下文中进行的。当您在发出函数调用的同一个线程中(或在主线程上)处理闭包时,这些注意事项可能不适用。