Networking with Async Await

Alex Logan
3 min readJun 21, 2021
Photo by Robert Nelson on Unsplash

At some point as iOS engineers, we’ve all had to deal with some messy network code. Whilst the closure based syntax of async work in Swift can be managed, with more complex operations things can get out of hand pretty quickly.

Now we have async await, we can say goodbye to code that looks like this.

Whilst it might seem like ive created a purposefully hard to read example of a networking call here, I’ve found very similar looking code in many apps I’ve worked on — including my own ( I’m looking at you Bike Settings 1.0 ).

Making Requests

async networking is wonderfully simple to use. There’s some new methods on URLSession that will do the heavy lifting for us.
The basic new look for networking is this. We can await the new async data(from: URL) which will return a tuple of the data and response. The response is a basic URLResponse, you'll most likely want to cast that to an HTTPURLResponse instead to read status codes.

*If you’re not too familiar with async yet, don’t worry — its brand new. I’ll be covering the basics of async in a later post.*

We have to mark our calls to URLSession methods with try as they can throw errors just like usual. This means we should either wrap in a do catch, or mark the function that calls this with async throws.
If you want to do more than just get something, you can also perform URLRequests with a similar method.

Lets look at a more complete example, that adds an authentication header, makes a request, then decodes the response into a Codable. This is exactly the same as the code we saw in the intro, but using our new async methods to clean things up.

If we break that down, its doing quite a lot, and its all very readable. It gets a token, which could itself perform a network request, checks the response code is valid, then returns a decoded JSON.

This setup code will be very familiar to you because its exactly what you’d do now — the cool part is waiting for our result without using closures.

if you wanted to upload some data instead, its just a couple small changes. Set the method to post, and attatch the json data.

Downloading & Uploading

We’re not always just posting or asking for JSON — sometimes we have more to do. Its quite common to have to deal with file uploads, such as profile pictures, and we’re luckily going to get some help here too.

Uploading has a similar new method to data tasks, upload(for: URLRequest, from: Data) and using it looks something like this.

Downloading is just as simple, with download(for: URLRequest). The setup code in all these examples is just about the same, with just some method changes.

The URL returned here will contain our downloaded file. If you use the sample code and open tyhat URL, you will find the file with a .tmp extension.

Conclusion

That was a quick intro to how you can use async/await in your codebase for networking. Its nice and simple, with scope to really clean up your code. All I’ve shown today is what its like at the network point — this cleanup continues as you go through the layers of your app.

Head to the repo and open 001-async-networking to run this code for yourself. You’ll find fully working code samples ( with exceptions for where I don’t have any mock endpoints — sorry! ) that you can lift and take into your own projects. For a challenge, why not try displaying a list of characters in a SwiftUI list?

If you’d like to take this even further, you could even build a full network stack using the new await apis based on the code i’ve provided. I would suggest going around and removing some duplicated code from my examples, and considering adding a nice typed system to represent endpoints.

If you fancy reading a little more, I’m @SwiftyAlex on twitter.

--

--