在SwiftUI中,从异步块内部变异@State变量安全吗



我有下面的结构(View(,它在内部使用async/await。

struct CachedAsyncImage<I: View, P: View>: View {
@State var image: UIImage?

let content: (Image) -> I
let placeholder: () -> P
let url: URL?

public init(
url: URL?,
@ViewBuilder content: @escaping (Image) -> I,
@ViewBuilder placeholder: @escaping () -> P
) {
self.url = url
self.content = content
self.placeholder = placeholder
}

var body: some View {
async {
guard let url = self.url else {
return
}

let session = URLSession.shared
let taskResponse = try? await session.data(from: url, delegate: nil)

guard let imageData = taskResponse?.0,
let uiImage = UIImage(data: imageData) else {
return
}

image = uiImage
}

guard let image = self.image else {
return AnyView(placeholder())
}

return AnyView(content(Image(uiImage: image)))
}
}

我使内部视图(IP类型(进行相应交换的唯一方法是从异步块内部分配必须用@State属性包装器标记的image属性。从线程/线程安全的角度来看,这是一种安全的做法吗?还是我必须以其他方式来实现它?

是(但应该在.task.task(id:)修饰符中执行,而不是直接在主体中执行(。

您可以安全地从任何线程更改状态属性。

https://developer.apple.com/documentation/swiftui/state

在Swift中,应该尝试使用structs之类的值类型而不是对象的原因之一。

从主线程之外的另一个线程更新UI数据是不安全的。Swift的并发模型并不能保证异步代码在哪个线程上运行。

因此,你的问题的答案是一个很大的NO。

您将需要在主线程上调度属性更新。主要演员是推荐的方法。

只需为这个添加一个新功能

@MainActor func updateImage(to newImage: UIImage) {
image = newImage
}

,并从异步任务调用它:

await updateImage(to: uiImage)

相关内容

  • 没有找到相关文章

最新更新