[英]How to capture local variable inside an async closure in Swift?
我在 Swift 5.5 和 iOS 15 中有以下代码
func getReviewIds() {
var reviewIds: [Int] = []
Task {
let ids = await getReviewIdsFromGoogle()
reviewIds.append(contentsOf: ids)
}
print("outside")
}
func getReviewIdsFromGoogle() async -> [Int] {
await withUnsafeContinuation { continuation in
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
continuation.resume(returning: [1,2,3])
}
}
}
我在以下行的getReviewIdsFromGoogle
function 中收到错误:
reviewIds.append(contentsOf: ids)
Mutation of captured var 'reviewIds' in concurrently-executing code
我知道我可以将getReviewIdsFromGoogle
async
function 而不是使用async
闭包,但是如何使用闭包解决这个问题。
为了防止数据竞争,您必须使用同步访问来自并发操作的变量,并且编译器不允许您直接更改数组。 为避免该问题,您可以使用actor
实例实现对数据的隔离访问,例如:
actor Store {
var reviewIds: [Int] = []
func append(ids: [Int]) {
reviewIds.append(contentsOf: ids)
}
}
func getReviewIds() {
let store = Store()
Task {
let ids = await getReviewIdsFromGoogle()
await store.append(ids: ids)
print(await store.reviewIds)
}
}
一旦启动了异步上下文,就无法将数据传回原始同步上下文,因为这将要求原始上下文在等待异步结果时“阻塞”。 Swift 不允许在其并发 model 中阻塞,因为这可能导致线程死锁。
您只需使用来自Task
上下文的结果调用另一个 function 来处理返回的值。 这个过程是否是另一个async
function 取决于您,这取决于您需要做什么。
func getReviewIDs() {
Task {
let result = await getReviewIdsFromGoogle()
process(ids: result)
}
}
func process(ids: [Int]) {
print("now process ids: \(ids)")
}
func getReviewIdsFromGoogle() async -> [Int] {
await withUnsafeContinuation { continuation in
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
continuation.resume(returning: [1,2,3])
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.