在 iTunesU 的 CS193P 斯坦福讲座中,讲师在第 8 课 30:14 提到多线程,您提供给异步调用的闭包“不接受任何参数并且不返回任何参数”。这让我感到惊讶,因为不久之后他给出了一个 iOS 方法的示例 (37:01),其中闭包能够返回参数,即:
let task = session.dataTask(with: url) { (data: Data?, response, error ) in ...
还有许多其他 iOS 方法似乎会向其完成闭包返回参数。我在这里错过了什么吗?为什么异步调用提供的闭包不能以与上面的 dataTask 调用类似的方式返回参数。
最佳答案
dataTask(with:)
与 DispatchQueue
的 async
不同。
首先,请记住您使用的是 trailing closure .当函数的最后一个参数是闭包(即代码“ block ”)时,闭包可以放在括号之外。以下代码使用了尾随闭包语法:
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
接受一个接受三个参数的闭包。这些功能中的任何一个都没有什么“神奇”之处;它们只是接受闭包,如果愿意,您可以编写自己的函数来接受闭包。
关于提供给异步调用的 Swift 闭包不接受任何参数也不返回任何参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43058062/