Swift 6.2 Default Concurrency Isolation and @concurrent
Apple is finally listening to feedback and simplifying asynchronous behavior in Swift Concurrency.
As I continue working on the Async Chapter of The iOS Interview Guide 2.0, I keep updating it with new additions to the Swift language. With the release of Swift 6.2, announced at WWDC 2025, a significant change was introduced to the default behavior in Swift Concurrency.
Since Swift 5.5, we’ve had actors that were designed to prevent data races. Actors ensure that only one piece of code (and only one thread at a time) can access its internal mutable state at any given time. This provides a safe and isolated context for async work execution.
However, working with actors, isolations, and the varying contexts of thread/queue execution (whether implicit or explicit) sometimes became very complex and challenging to manage.
In Swift 6.2, Apple changed this, attempting to simplify things by making everything in your app single-threaded by default. Simply put, now, everything runs on the @MainActor implicitly by default if you have the SWIFT_DEFAULT_ACTOR_ISOLATION build setting flag turned on. For brand new projects starting with Xcode 26, it’s going to be the default.
What this really means is the return to “old” behavior where your code implicitly, by default, runs on the main thread unless you specify otherwise.
There are basically three ways to run your async code off of the main thread in a background thread:
Use an actor
Use @concurrent function.
Use Task/Task.detached
Actors’ purpose is to hold a “safe” state that can be altered and accessed over multiple async operations from different threads, and @concurrent’s purpose is to run a one-off async job (for a stateless computation) on a background thread off of the main thread.
Conclusion
This new default threading behavior is a welcome change to the previously confusing, convoluted implementation of asynchronicity that Apple created in Swift. I’m glad they are listening this year and are making sensible changes for a change.
IMO, this is the implementation that they should’ve aimed for from the get-go as they introduced structured concurrency. It’s a more natural mental model and a safer assumption for every developer to think that, by default, everything is executed on the main thread. After all, this is how every other client-side platform works, and that’s how it was prior to Swift Concurrency.
As for my own projects… I’m still sticking with RxSwift :)
RxSwift vs Async/Await
I’m a bit conflicted when it comes to my opinion and preferences towards using RxSwift vs Async/Await for async operations. I rewrote this article multiple times trying to refine my thinking, hopefully this one captures it, so hear me out.