SwiftUI architecture with background tasks

Viewed 273

I am writing my first SwiftUI app which needs to be performing various tasks in the background; such as occasionally fetching data from an API, responding to web socket events, stuff like that.

My question is, where is the best place to kick off such background tasks? One thought is Task block hanging off the WindowGroup but I really have no proper clue. Any resources anyone can recommend about the architecture of SeiftUI apps? I’m following the MVI pattern.

1 Answers

You can use the new .task() modifier to the view. Here's an example of downloading an image asynchronously:

struct MyView: View {

    @State private var myImage: UIImage? = nil
    
    var body: some View {
        Group {
            if myImage == nil {
                ProgressView()
            } else {
                Image(uiImage: myImage!)
                    .resizable()
                    .scaledToFit()
            }
        }

        // The code in this closure will run asynchronously
        // when the view launches
        .task {

            // Create your usual URLRequest in some function
            // and use it here
            // (URLRequest to return data)
            let downloadedImage = await UIImage(data: myURLRequestHere())) ?? UIImage()

            // This code will run only after downloadedImage has finished
            // the task marked with "await"
            updateImageWith(image: downloadedImage)
        }
    }

    // Using @MainActor ensures that you are updating the
    // UI in the main thread
    @MainActor func updateImageWith(image: UIImage) {
        withAnimation {
            myImage = image
        }
    }
}
Related