How to run async function (URLSession) inside a Publisher .onReceive

196 views Asked by At

What would be the proper way to avoid Task {} inside a .onReceive() closure and still be able to run async code?

If I add a Task {} everything runs as it should but shouldn't I replace all Task {} blocks in swiftui? Whenever possible I'm using .task directly on the view but in this case I need to run an URLSession from a publisher onReceive closure.

1

There are 1 answers

7
lorem ipsum On BEST ANSWER

You can have the onReceive alter a variable that serves as an id for task.

struct TestURLSessionOnReceive: View {
    //Object from the publisher/task id
    @State private var id: UUID?
    //Result from async task
    @State private var progress: String?
    var body: some View {
        VStack{
            Button("post notification") { //Mocking a publisher trigger
                NotificationCenter.default.post(name: .someNotification, object: UUID.init().uuidString)
            }
            if let progress { //Mocking a result from an async task
                ProgressView {
                    Text(progress)
                }
            }
        }
        //Listen for the publisher
        .onReceive(NotificationCenter.default.publisher(for: .someNotification), perform: { notification in
            guard let uuidString = notification.object as? String, let uuid = UUID(uuidString: uuidString) else {
                return
            }
            self.id = uuid
        })
        //Complete a task based on a publisher
        .task(id: id) {
            guard let id else {return} //Ignore the "onAppear" call
            progress = "Working on\nid = \(id)"
            //Do any async await code
            
            //let (data, response) = try await URLSession.shared.data(from: <#T##URL#>)
            try? await Task.sleep(for: .seconds(2)) //Mocking async task
            
            progress = nil
        }
    }
}

extension Notification.Name {

    static let someNotification = Notification.Name("someNotification")
}