From 2f499fcceed6edfb334bbcb0f55f361846f181e7 Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Wed, 7 Jan 2026 07:35:07 +0100 Subject: [PATCH] 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. --- swift-concurrency-expert/SKILL.md | 2 + .../references/approachable-concurrency.md | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 swift-concurrency-expert/references/approachable-concurrency.md diff --git a/swift-concurrency-expert/SKILL.md b/swift-concurrency-expert/SKILL.md index 4697ac3..b04438d 100644 --- a/swift-concurrency-expert/SKILL.md +++ b/swift-concurrency-expert/SKILL.md @@ -14,6 +14,7 @@ Review and fix Swift Concurrency issues in Swift 6.2+ codebases by applying acto ### 1. Triage the issue - Capture the exact compiler diagnostics and the offending symbol(s). +- Check project concurrency settings: Swift language version (6.2+), strict concurrency level, and whether approachable concurrency (default actor isolation / main-actor-by-default) is enabled. - Identify the current actor context (`@MainActor`, `actor`, `nonisolated`) and whether a default actor isolation mode is enabled. - Confirm whether the code is UI-bound or intended to run off the main actor. @@ -32,4 +33,5 @@ Common fixes: ## Reference material - See `references/swift-6-2-concurrency.md` for Swift 6.2 changes, patterns, and examples. +- See `references/approachable-concurrency.md` when the project is opted into approachable concurrency mode. - See `references/swiftui-concurrency-tour-wwdc.md` for SwiftUI-specific concurrency guidance. diff --git a/swift-concurrency-expert/references/approachable-concurrency.md b/swift-concurrency-expert/references/approachable-concurrency.md new file mode 100644 index 0000000..b495d13 --- /dev/null +++ b/swift-concurrency-expert/references/approachable-concurrency.md @@ -0,0 +1,63 @@ +## 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/