Using Swift’s async/await to build an image loader

Published on: September 6, 2021

Async/await will be the defacto way of doing asynchronous programming on iOS 15 and above. I've already written quite a bit about the new Swift Concurrency features, and there's still plenty to write about. In this post, I'm going to take a look at building an asynchronous image loader that has support for caching. SwiftUI on iOS 15 already has a component that allows us to load images from the network but it doesn't support caching (other than what’s already offered by URLSession), and it only works with a URL rather than also accepting a URLRequest. The component will be...

Read more...

What exactly is a Combine AnyCancellable?

Published on: August 24, 2021

If you've worked with Combine at all in your applications you'll know what it means when I tell you that you should always retain your cancellables. Cancellables are an important part of working with Combine, similar to how disposables are an important part of working with RxSwift. For example, you might have built a publisher that wraps CLLocationManagerDelegate and exposes the user's current location with a currentLocation publisher that's a CurrentValueSubject<CLLocation, Never>. If you subscribe to this publisher it might look a bit like this: struct ViewModel { let locationProvider: LocationProvider var cancellables = Set<AnyCancellable>() init(locationProvider: LocationProvider) { self.locationProvider =...

Read more...

Building a token refresh flow with async/await and Swift Concurrency

Published on: August 16, 2021

One of my favorite concurrency problems to solve is building concurrency-proof token refresh flows. Refreshing authentication tokens is something that a lot of us deal with regularly, and doing it correctly can be a pretty challenging task. Especially when you want to make sure you only issue a single token refresh request even if multiple network calls encounter the need to refresh a token. Furthermore, you want to make sure that you automatically retry a request that failed due to a token expiration after you've obtained a new (valid) authentication token. I wrote about a flow that does this before,...

Read more...

Using Swift Concurrency’s task group for tasks with varying output

Published on: August 9, 2021

Earlier, I published a post on Swift Concurrency's task groups. If you haven't read that post yet, and you're not familiar with task groups, I recommend that you read that post first because I won't be explaining task groups in this post. Instead, you will learn about a technique that you can use to work around a limitation of task groups. Task groups can run a number of child tasks where every child task in the task group produces the same output. This is a hard requirement of the withTaskGroup function. This means that task groups are not the right...

Read more...

Running tasks concurrently with Swift Concurrency’s async let

Published on: August 9, 2021

In last week's post, I demonstrated how you can use a task group in Swift to concurrently run multiple tasks that produce the same output. This is useful when you're loading a bunch of images, or in any other case where you have a potentially undefined number of tasks to run, as long as you (somehow) make sure that every task in your group produces the same output. Unfortunately, this isn't always a reasonable thing to do. For example, you might already know that you only have a very limited, predetermined, number of tasks that you want to run. These...

Read more...

Running tasks in parallel with Swift Concurrency’s task groups

Published on: August 5, 2021

With Apple's overhaul of how concurrency will work in Swift 5.5 and newer, we need to learn a lot of things from scratch. While we might have used DispatchQueue.async or other mechanisms to kick off multiple asynchronous tasks in the past, we shouldn't use these older concurrency tools in Swift's new concurrency model. Luckily, Swift Concurrency comes with many features already which means that for a lot of our old uses cases, a new paradigm exists. In this post, you will learn what Swift Concurrency's task groups are, and how you can use them to concurrently perform a lot of...

Read more...

Using UISheetPresentationController in SwiftUI

Published on: June 30, 2021

With iOS 15, Apple introduced the ability to easily implement a bottom sheet with UISheetPresentationController in UIKit. Unfortunately, Apple didn't extend this functionality to SwiftUI just yet (I'm hoping one of the iOS 15 betas adds this...) but luckily we can make use of UIHostingController and UIViewRepresentable to work around this limitation and use a bottom sheet on SwiftUI. In this post, I will show you a very simple implementation that might not have everything you need. After I tweeted about this hacky little workaround, someone suggested this very nice GitHub repository from Adam Foot that works roughly the same...

Read more...

Presenting a bottom sheet in UIKit with UISheetPresentationController

Published on: June 30, 2021

We've seen bottom sheets in Apple's apps for a while now, and plenty of apps have followed this pattern. If you're not sure what I mean, it's the kind of sheet that takes up just a part of the screen and can be swiped upwards to take up the whole screen or downwards to be dismissed. Here's an example from Apple's Maps app: To implement a sheet like this, we used to require third party tools, or we needed to get creative and implement this pattern ourselves. With iOS 15, Apple introduced UISheetPresentationController which allows us to implement bottom sheets...

Read more...

What are Swift Concurrency’s task local values?

Published on: June 22, 2021

If you've been following along with Swift Concurrency in the past few weeks, you might have come across the term "task local values". Task local values are, like the name suggests, values that are scoped to a certain task. These values are only available within the context they're scoped to, and they are really only supposed to be used in a handful of use cases. In this post, I will explain what task local are, and more importantly I will explain how and when they are useful. For a full rundown of task local values and their design I'd like...

Read more...

An introduction to synchronizing access with Swift’s Actors

Published on: June 14, 2021

We all know that async / await was one of this year’s big announcements WWDC. It completely changes the way we interact with concurrent code. Instead of using completion handlers, we can await results in a non-blocking way. More importantly, with the new Swift Concurrency features, our Swift code is much safer and consistent than ever before. For example, the Swift team built an all-new threading model that ensures your program doesn’t spawn more threads than there are CPU cores to avoid thread explosion. This is a huge difference from GCD where every call to async would spawn a new...

Read more...