I have the following struct (View) that uses async/await internally.
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))) } } The only way I made the internal views (I and P types) to swap accordingly was to assign the image property, which had to be marked with the @State property wrapper, from inside the async block. Is this a safe practice from a threading/thread-safety perspective or do I have to implement it in some other way?
URLSessionevery time thebodyof theViewis rendered is a good idea. Maybe useonAppearon the new.taskinstead?View. This was meant to be a minimal example.