Recent articles

Jump to a random post

Opting your app out of the Liquid Glass redesign with Xcode 26

Published on: June 10, 2025

On iOS 26, iPadOS 26 and more, your apps will take on a whole new look based on Apple's Liquid Glass redesign. All you need to do to adopt this new style in your apps is recompile. Once recompiled, your app will have all-new UI components which means your app will look fresh and right at home in Apple's latest OS. That said, there are many reasons why you might not want to adopt Liquid Glass just yet. It's a big redesign and for lots of apps there will be work to do to properly adapt your designs to fit...

Read more...

Setting default actor isolation in Xcode 26

Published on: June 10, 2025

With Swift 6.2, Apple has made a several improvements to Swift Concurrency and its approachability. One of the biggest changes is that new Xcode projects will now, by default, apply an implicit main actor annotation to all your code. This essentially makes your apps single-threaded by default. I really like this change because without this change it was far too easy to accidentally introduce loads of concurrency in your apps. In this post I'd like to take a quick look at how you can control this setting as well as the setting for nonisolated(nonsending) from Xcode 26's build settings menu....

Read more...

Exploring concurrency changes in Swift 6.2

Published on: May 20, 2025

It's no secret that Swift concurrency can be pretty difficult to learn. There are a lot of concepts that are different from what you're used to when you were writing code in GCD. Apple recognized this in one of their vision documents and they set out to make changes to how concurrency works in Swift 6.2. They're not going to change the fundamentals of how things work. What they will mainly change is where code will run by default. In this blog post, I would like to take a look at the two main features that will change how your...

Read more...

Enabling upcoming feature flags in an SPM package

Published on: May 19, 2025

As Swift evolves, a lot of new evolution proposals get merged into the language. Eventually these new language versions get shipped with Xcode, but sometimes you might want to try out Swift toolchains before they're available inside of Xcode. For example, I'm currently experimenting with Swift 6.2's upcoming features to see how they will impact certain coding patterns once 6.2 becomes available for everybody. This means that I'm trying out proposals like SE-0461 that can change where nonisolated async functions run. This specific proposal requires me to turn on an upcoming feature flag. To do this in SPM, we need...

Read more...

Should you use network connectivity checks in Swift?

Published on: May 16, 2025

A lot of modern apps have a networking component to them. This could be because your app relies on a server entirely for all data, or you’re just sending a couple of requests as a back up or to kick off some server side processing. When implementing networking, it’s not uncommon for developers to check the network’s availability before making a network request. The reasoning behind such a check is that we can inform the user that their request will fail before we even attempt to make the request. Sound like good UX, right? The question is whether it really...

Read more...

Choosing between LazyVStack, List, and VStack in SwiftUI

Published on: May 8, 2025

SwiftUI offers several approaches to building lists of content. You can use a VStack if your list consists of a bunch of elements that should be placed on top of each other. Or you can use a LazyVStack if your list is really long. And in other cases, a List might make more sense. In this post, I’d like to take a look at each of these components, outline their strengths and weaknesses and hopefully provide you with some insights about how you can decide between these three components that all place content on top of each other. We’ll start...

Read more...

Differences between Thread.sleep and Task.sleep explained

Published on: May 1, 2025

In Swift, we have several ways to “suspend” execution of our code. While that’s almost always a bad practice, I’d like to explain why Task.sleep really isn’t as problematic as you might expect when you’re familiar with Thread.sleep. When you look for examples of debouncing or implementing task timeout they will frequently use Task.sleep to suspend a task for a given amount of time. The key difference is in how tasks and threads work in Swift. In Swift concurrency, we often say that tasks replace threads. Or in other words, instead of worrying about threads, we worry about tasks. While...

Read more...

Protecting mutable state with Mutex in Swift

Published on: April 30, 2025

Once you start using Swift Concurrency, actors will essentially become your standard choice for protecting mutable state. However, introducing actors also tends to introduce more concurrency than you intended which can lead to more complex code, and a much harder time transitioning to Swift 6 in the long run. When you interact with state that’s protected by an actor, you have to to do so asynchronously. The result is that you’re writing asynchronous code in places where you might never have intended to introduce concurrency at all. One way to resolve that is to annotate your let's say view model...

Read more...

Using singletons in Swift 6

Published on: April 23, 2025

Singletons generally speaking get a bad rep. People don’t like them, they cause issues, and generally speaking it’s just not great practice to rely on globally accessible mutable state in your apps. Instead, it’s more favorable to practice explicit dependency passing which makes your code more testable and reliable overall. That said, sometimes you’ll have singletons. Or, more likely, you’ll want to have a a shared instance of something that you need in a handful of places in your app: class AuthProvider { static let shared = AuthProvider() // ... } In Swift 6, this will lead to issues because...

Read more...

Using Instruments to profile a SwiftUI app

Published on: April 16, 2025

A key skill for every app developer is being able to profile your app's performance. Your app might look great on the surface, but if it doesn’t perform well, it’s going to feel off—sometimes subtly, sometimes very noticeably. Beautiful animations, slick interactions, and large data sets all fall flat if the app feels sluggish or unresponsive. Great apps respond instantly. They show that you’ve tapped something right away, and they make interactions feel smooth and satisfying. To make sure your app behaves like that, you’ll need to keep an eye on its performance. In this post, we’ll look at how...

Read more...