Using Swift 4, I have this code that attempts a POST request to a REST API:
spinner.startAnimation(self)
btnOk.isEnabled = false
btnCancel.isEnabled = false
attemptPost()
spinner.stopAnimation(self)
btnOk.isEnabled = true
btnCancel.isEnabled = true
The function that does this (Constants
and Request
are classes that I created that create the request objects and hold frequently used data):
func attemptPost() {
let url = Constants.SERVICE_URL + "account/post"
let body: [String : Any] =
["firstName": txtFirstName.stringValue,
"lastName": txtLastName.stringValue,
"email": txtEmail.stringValue,
"password": txtPassword.stringValue];
let req = Request.create(urlExtension: url, httpVerb: Constants.HTTP_POST, jsonBody: body)
let task = URLSession.shared.dataTask(with: req) { data, response, err in
guard let data = data, err == nil else {
// error
return
}
if let resp = try? JSONSerialization.jsonObject(with: data) {
// success
}
}
task.resume()
}
Since the task that does this runs asynchronously, there is no sequential way that I can update the UI once the call to attemptPost()
returns. And since the UI components are on the main thread, I can't directly update the components from the task that makes the request.
In C# it works the same way; there is a BackgroundWorker
class in which you can safely update the UI components to avoid a "Cross-thread operation not valid" error.
I'm trying to find an example that accomplishes more or less the same thing, in which a "wait" state is established, the task runs, and upon task completion, the main thread is notified that the task is done so that the wait state can be changed.
But I'm still having trouble understanding how this all comes together in Swift. I've looked around and seen information about the handlers that are invoked from within URLSessionDataTask
and stuff about GCD, but I'm still not able to connect the dots.
And is GCD even relevant here since the URLSessionDataTask
task is asynchronous to begin with?
Any help is appreciated.