Swift concurrency

Enabling Concurrency warnings in Xcode 15

Published on: September 13, 2022

If you want to make sure that your code adopts Swift concurrency as correctly as possible in Swift 5.x, it's a good idea to enable the Strict Concurrency Checking (SWIFT_STRICT_CONCURRENCY) flag in your project. To do this, select your project's target and navigate to the Build Settings tab. Make sure you select All from the list of settings that is shown (Basic is the default) and type Strict Concurrency in the searchbar to find the Strict Concurrency Checking build setting. The screenshot below shows all the relevant parts for you to see: The default value for this setting is Minimal...

Read more...

What are Sendable and @Sendable closures in Swift?

Published on: September 13, 2022

One of the goals of the Swift team with Swift’s concurrency features is to provide a model that allows developer to write safe code by default. This means that there’s a lot of time and energy invested into making sure that the Swift compiler helps developers detect, and prevent whole classes of bugs and concurrency issues altogether. One of the features that helps you prevent data races (a common concurrency issue) comes in the form of actors which I’ve written about before. While actors are great when you want to synchronize access to some mutable state, they don’t solve every...

Read more...

The difference between checked and unsafe continuations in Swift

Published on: April 24, 2022

When you’re writing a conversion layer to transform your callback based code into code that supports async/await in Swift, you’ll typically find yourself using continuations. A continuation is a closure that you can call with the result of your asynchronous work. You have the option to pass it the output of your work, an object that conforms to Error, or you can pass it a Result. In this post, I won’t go in-depth on showing you how to convert your callback based code to async/await (you can refer to this post if you’re interested in learning more). Instead, I’d like...

Read more...

Wrapping existing asynchronous code in async/await in Swift

Published on: April 24, 2022

Swift's async/await feature significantly enhances the readability of asynchronous code for iOS 13 and later versions. For new projects, it enables us to craft more expressive and easily understandable asynchronous code, which closely resembles synchronous code. However, adopting async/await may require substantial modifications in existing codebases, especially if their asynchronous API relies heavily on completion handler functions. Fortunately, Swift offers built-in mechanisms that allow us to create a lightweight wrapper around traditional asynchronous code, facilitating its transition into the async/await paradigm. In this post, I'll demonstrate how to convert callback-based asynchronous code into functions compatible with async/await, using Swift's async...

Read more...

Comparing lifecycle management for async sequences and publishers

Published on: April 12, 2022

In my previous post you learned about some different use cases where you might have to choose between an async sequence and Combine while also clearly seeing that async sequence are almost always better looking in the examples I’ve used, it’s time to take a more realistic look at how you might be using each mechanism in your apps. The details on how the lifecycle of a Combine subscription or async for-loop should be handled will vary based on how you’re using them so I’ll be providing examples for two situations: Managing your lifecycles in SwiftUI Managing your lifecycles virtually...

Read more...

Comparing use cases for async sequences and publishers

Published on: April 12, 2022

Swift 5.5 introduces async/await and a whole new concurrency model that includes a new protocol: AsyncSequence. This protocol allows developers to asynchronously iterate over values coming from a sequence by awaiting them. This means that the sequence can generate or obtain its values asynchronously over time, and provide these values to a for-loop as they become available. If this sounds familiar, that’s because a Combine publisher does roughly the same thing. A publisher will obtain or generate its values (asynchronously) over time, and it will send these values to subscribers whenever they are available. While the basis of what we...

Read more...

Understanding Swift’s AsyncSequence

Published on: November 1, 2021

The biggest features in Swift 5.5 all revolve around its new and improved concurrency features. There's actors, async/await, and more. With these features folks are wondering whether async/await will replace Combine eventually. While I overall do not think that async/await can or will replace Combine on its own, Swift 5.5 comes with some concurrency features that provide very similar functionality to Combine. If you're curious about my thoughts on Combine and async/await specifically, I still believe that what I wrote about this topic earlier is true. Async/await will be a great tool for work that have a clearly defined start...

Read more...

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...

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...