gh-Dimillian-Skills/swift-concurrency-expert/references/approachable-concurrency.md
Thomas Ricouard 2f499fccee Add guide for approachable concurrency in Swift 6.2
Updated SKILL.md to reference project concurrency settings and added a new reference guide for Swift 6.2 approachable concurrency mode. The new guide covers detection, expected behavior changes, recommended fixes, and common pitfalls for projects using main-actor-by-default and default actor isolation.
2026-01-07 07:35:07 +01:00

2.4 KiB

Approachable Concurrency (Swift 6.2) - project mode quick guide

Use this reference when the project has opted into the Swift 6.2 approachable concurrency settings (default actor isolation / main-actor-by-default).

Detect the mode

Check Xcode build settings under "Swift Compiler - Concurrency":

  • Swift language version (must be 6.2+).
  • Default actor isolation / Main Actor by default.
  • Strict concurrency checking level (Complete/Targeted/Minimal).

For SwiftPM, inspect Package.swift swiftSettings for the same flags.

Behavior changes to expect

  • Async functions stay on the caller's actor by default; they don't hop to a global concurrent executor unless the implementation chooses to.
  • Main-actor-by-default reduces data race errors for UI-bound code and global state, because mutable state is implicitly protected.
  • Protocol conformances can be isolated (e.g., extension Foo: @MainActor Bar).

How to apply fixes in this mode

  • Prefer minimal annotations; let main-actor-by-default do the work when the code is UI-bound.
  • Use isolated conformances instead of forcing nonisolated workarounds.
  • Keep global or shared mutable state on the main actor unless there is a clear performance need to offload it.

When to opt out or offload work

  • Use @concurrent on async functions that must run on the concurrent pool.
  • Make types or members nonisolated only when they are truly thread-safe and used off the main actor.
  • Continue to respect Sendable boundaries when values cross actors or tasks.

Common pitfalls

  • Task.detached ignores inherited actor context; avoid it unless you truly need to break isolation.
  • Main-actor-by-default can hide performance issues if CPU-heavy work stays on the main actor; move that work into @concurrent async functions.

Keywords (from source cheat sheet)

Keyword What it does
async Function can pause
await Pause here until done
Task { } Start async work, inherits context
Task.detached { } Start async work, no inherited context
@MainActor Runs on main thread
actor Type with isolated mutable state
nonisolated Opts out of actor isolation
Sendable Safe to pass between isolation domains
@concurrent Always run on background (Swift 6.2+)
async let Start parallel work
TaskGroup Dynamic parallel work

Source

https://fuckingapproachableswiftconcurrency.com/en/