swift6-concurrency
Installation
SKILL.md
Swift 6 / Strict Concurrency
When to invoke
- Starting a new Swift iOS / macOS App project and deciding the language mode.
- Writing
Package.swiftand settingswiftLanguageModes/SWIFT_STRICT_CONCURRENCY. - Adding a new third-party dependency and hitting concurrency warnings / errors.
- User asks "how do I configure Swift 6 / complete concurrency / Sendable / actor /
@preconcurrency".
Default decisions
- Swift 6 language mode + complete concurrency checking, applied from the first line of code.
- Default actor isolation is
MainActor, following the Xcode 26 App project template (SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor+SWIFT_APPROACHABLE_CONCURRENCY = YES; the SwiftPM equivalent isswiftSettings: [.defaultIsolation(MainActor.self)], which requires// swift-tools-version: 6.2). Under this default an unannotated in-house type never leaves the main actor, so it does not needSendableon its own account —Sendableis required only for a type that crosses intononisolatedcode, an actor, or a module with a different isolation default. Declare it explicitly when it does (struct Foo: Sendableorfinal class Foo: Sendable— the latter only valid when the class is non-inheritable and every stored property is bothSendableandlet; for classes with mutable state, preferactor Fooor@unchecked Sendablewith manual synchronisation). - Layer the isolation default per module (see
swiftpm-modularization): keepMainActoras the default for UI/App modules; Engine/Domain modules that are pure logic setswiftSettings: [.defaultIsolation(nil)]so they staynonisolatedby default and avoid needless main-actor hops. Work that must run off the main actor is marked explicitly with@concurrent(SE-0461) rather than left to inference. - Protocols that cross actor boundaries (DI injection points) are declared
Sendable, with methodsasync throws. Keep that requirement even when the implementation is an actor: the protocol'sSendableis not what fails when a non-Sendableframework type (AVAssetTrack,VNRequest) is involved — what fails is the value crossing the boundary: