更新2:我怀疑问题被点赞是因为我描述了可能的解决方案。为了更清晰,我将其加粗。
更新1:这个问题有很多浏览量。如果你认为自己遇到的错误情况可以增强这个问题,请在评论中简要描述你的情况,这样我们就可以使这个问答更有价值。如果你有解决问题的方案,请将其作为答案添加。
我想在使用Task.detached
和async
函数执行异步后台工作后更新UI。
然而,在构建期间,我遇到了Reference to captured var 'a' in concurrently-executing code
错误的构建错误。
我尝试了一些方法,只有在更新UI之前将变量转换为let常量
才能正常工作。为什么我需要在能够更新UI之前将其变成一个let常量?还有其他替代方法吗?
class ViewModel: ObservableObject {
@Published var something: String?
init() {
Task.detached(priority: .userInitiated) {
await self.doVariousStuff()
}
}
private func doVariousStuff() async {
var a = "a"
let b = await doSomeAsyncStuff()
a.append(b)
something = a /* Not working,
Gives
- runtime warning `Publishing changes from
background threads is not allowed; make sure to
publish values from the main thread (via operators
like receive(on:)) on model updates.`
or, if `something` is @MainActor:
- buildtime error `Property 'something' isolated
to global actor 'MainActor' can not be mutated
from this context`
*/
await MainActor.run {
something = a
} /* Not working,
Gives buildtime error "Reference to captured var 'a'
in concurrently-executing code" error during build
*/
DispatchQueue.main.async {
self.something = a
} /* Not working,
Gives buildtime error "Reference to captured var 'a'
in concurrently-executing code" error during build
*/
/*
This however, works!
*/
let c = a
await MainActor.run {
something = c
}
}
private func doSomeAsyncStuff() async -> String {
return "b"
}
}