func doSomething(using closure: () -> Void) {
closure()
}
传递给doSomething(using :)的闭包在doSomething(using :)函数中立即执行。 因为闭包是在doSomething(using :)范围内立即执行的,所以我们知道在闭包内部所做的任何事情都不会泄漏或超过doSomething(using :)范围的寿命。 如果我们在doSomething(using :)中进行关闭操作或保留函数作用域,则会收到编译器错误:
func doSomething(using closure: () -> Void) {
DispatchQueue.main.async {
closure()
}
}
上面的代码将导致编译器错误,因为Swift现在可以看到,当我们调用doSomething(using :)时,传递给该函数的闭包将转义其范围。这意味着我们需要将其标记为故意的,因此doSomething(using :)的调用者将知道他们正在处理一个闭包,该闭包将超过传递给它的函数的范围,这意味着他们需要采取措施预防循环引用或内存泄露。除了向调用者告知转义闭包doSomething(using :)之外,它还告诉Swift编译器我们知道闭包保留了传递给它的作用域,对此我们可以接受。
您通常会看到转义闭包以执行异步工作并将函数作为回调调用闭包。例如,URLSession.dataTask(with:completionHandler :)的completionHandler标记为@escaping,因为在请求完成后即完成数据处理程序后即创建数据任务之后的某个时间,由于完成处理程序传递的闭包被执行。如果您编写的代码带有完成处理程序并使用数据任务,则您接受的闭包也必须标记为@escaping。
func makeRequest(_ completion: @escaping (Result<(Data, URLResponse), Error>) -> Void) {
URLSession.shared.dataTask(with: URL(string: "https://donnywals.com")!) { data, response, error in
if let error = error {
completion(.failure(error))
} else if let data = data, let response = response {
completion(.success((data, response)))
}
assertionFailure("We should either have an error or data + response.")
}
}
请注意,在上方的结束代码中,标记为@escaping,是因为我在数据任务的完成处理程序中使用了它。 这意味着,在makeRequest(_ :)退出作用域之前,不会执行completion闭包,并且completion闭包的生命周期更长。
简而言之,@escaping用于通知采取闭包的函数的调用者,该闭包可能已存储或超出了接收函数的范围。 这意味着调用方必须采取预防措施,以防止循环引用和内存泄漏。
译自:What is @escaping in Swift? – Donny Wals
今天的文章 Swift中的@escaping是什么?分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/102283.html