提供给异步调用的Swift闭包不带任何参数也不返回任何参数

时间:2017-03-27 23:22:59

标签: swift multithreading asynchronous closures

在CS193P上,斯坦福大学讲课的讲师在第8讲中提到了多线程,我们在多线程中提到你为异步调用提供的闭包“没有参数,也没有返回任何参数”。这让我感到惊讶,因为不久之后他给出了一个iOS方法的例子(37:01),其中闭包能够返回参数,即:

let task = session.dataTask(with: url) { (data: Data?, response, error ) in  ...

还有许多其他iOS方法似乎返回完成闭包的参数。我在这里错过了什么吗?为什么不能通过异步调用提供的闭包以与上面的dataTask调用类似的方式返回参数。

2 个答案:

答案 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
)

groupqosflags都有默认值,因此可以在此处忽略它们。重要的部分是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的特定上下文中进行的。当您在发出函数调用的同一个线程中(或在主线程上)处理闭包时,这些注意事项可能不适用。