Trying to to convert my old URL functionality to SwiftUI with async/await. While the skeleton below works, am puzzled as to why I must place my call to the method within a Task? When I don't use Task I get the error:
Cannot pass function of type '() async -> Void' to parameter expecting synchronous function type
From the examples I've seen, this wasn't necessary.
So I either I've misunderstood something, or I am doing this incorrectly, and am looking for little but of guidance.
Thank you
Within my SwiftUI view:
Button {
Task {
let request = xFile.makePostRequest(xUser: xUser, script: "requestTicket.pl")
var result = await myNewURL.asyncCall(request: request)
print("\(result)")
}
}
From a separate class:
class MyNewURL: NSObject, ObservableObject {
func asyncCall(request: URLRequest) async -> Int {
do {
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse
else {
print("error")
return -1
}
if httpResponse.statusCode == 200 {
...
}
} catch {
return -2
}
return 0
}
}
You have to wrap calls to async functions in a Task block if the function or closure where you make the call does not support Swift's async await
syntax. If you are getting build errors if you remove the Task block, it's a sign the function or closure does not support the async await
syntax. See the following article for additional explanation:
https://www.swiftdevjournal.com/fixing-the-async-call-in-a-function-that-doesnt-support-concurrency-error-in-swift/
SwiftUI has a .task
modifier you can use to make an async call from a SwiftUI view. You may be able to use it to avoid having to wrap your button code in a Task block. See the following article for an introduction to the .task
modifier:
https://www.hackingwithswift.com/quick-start/concurrency/how-to-run-tasks-using-swiftuis-task-modifier