Skip to content
Development
Skill

/concurrency

Swift 6.2 concurrency updates including default MainActor inference, @concurrent for background work, isolated conformances, and approachable concurrency migration. Use when adopting Swift 6.2 concurrency features or fixing data-race errors.

From plugin
rshankras-apple-skills
603183 skills
Install
$ npx -y skills add rshankras/claude-code-apple-skills --skill concurrency --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/concurrency

Context preview

The summary Claude sees to decide when to auto-load this skill.

Swift 6.2 concurrency updates including default MainActor inference, @concurrent for background work, isolated conformances, and approachable concurrency migration. Use when adopting Swift 6.2 concurrency features or fixing data-race errors.

SKILL.md

concurrency.SKILL.md
name: swift-concurrency-updates
description: Swift 6.2 concurrency updates including default MainActor inference, @concurrent for background work, isolated conformances, and approachable concurrency migration. Use when adopting Swift 6.2 concurrency features or fixing data-race errors.
allowed-tools: [Read, Glob, Grep]
last_verified: 2026-07-16
review_by: 2027-06-22
os_version: iOS 27 / macOS 27

Swift 6.2 Concurrency Updates

Swift 6.2 introduces "Approachable Concurrency" -- a set of changes that make strict concurrency dramatically easier to adopt. Code runs on `@MainActor` by default, async functions stay on the calling actor, and you explicitly request background execution with `@concurrent`.

This skill covers only the Swift 6.2 specific changes. For general concurrency patterns (actors, TaskGroup, AsyncSequence, Sendable, cancellation), see the `swift/concurrency-patterns` skill.

When This Skill Activates

  • User is adopting Swift 6.2 concurrency features
  • User asks about default MainActor inference or the "infer main actor" build setting
  • User encounters data-race errors that Swift 6.2 resolves
  • User asks about `@concurrent`, isolated conformances, or approachable concurrency
  • User wants to migrate from Swift 6.0/6.1 strict concurrency to 6.2
  • User asks how async functions behave differently in Swift 6.2
  • User needs to offload CPU-intensive work to a background thread in Swift 6.2

What Changed in Swift 6.2 vs Before

Swift 6.2 Changes at a Glance

| Feature | Before (6.0/6.1) | After (6.2) | |---------|------------------|-------------| | Default isolation | Nothing inferred; manual `@MainActor` everywhere | Opt-in mode infers `@MainActor` on everything | | Async function execution | Hops to generic concurrent executor | Stays on calling actor | | `@MainActor` type conforming to protocol | Compiler error for non-isolated protocols | Isolated conformances: `@MainActor Protocol` | | Background execution | `Task.detached` or manual nonisolated functions | `@concurrent` attribute | | Global/static mutable state | Required `@MainActor` annotation or Sendable | Default MainActor mode handles it automatically |

---

1. Async Functions Stay on the Calling Actor

In Swift 6.2, async functions without specific actor isolation stay on whatever actor called them, instead of hopping to the generic concurrent executor as in 6.0/6.1 -- eliminating a common source of data-race errors with no code changes required.

---

2. Default MainActor Inference Mode

An opt-in build setting that makes all code implicitly `@MainActor` unless explicitly opted out with `nonisolated`.

Enabling It

**Xcode:** Build Settings > Swift Compiler - Concurrency > "Default Actor Isolation" > "MainActor"

**Swift Package Manager:**

.executableTarget(
    name: "MyApp",
    swiftSettings: [
        .defaultIsolation(MainActor.self)
    ]
)

With this enabled, app-level types no longer need explicit `@MainActor` annotations -- including global/static mutable state, which otherwise needs an explicit `@MainActor static let ...`.

When to Use Default MainActor Inference

| Target Type | Recommended? | Reason | |-------------|-------------|--------| | App target | Yes | Apps are UI-driven; most code belongs on MainActor | | Script / executable | Yes | Scripts are sequential; MainActor default is natural | | Library / framework | No | Libraries must not impose actor isolation on consumers | | Package plugin | No | Same reasoning as libraries |

Opting Out with nonisolated

When a type or function genuinely needs to run off the main actor, mark it `nonisolated`:

nonisolated struct ImageProcessor {
    func processImage(_ data: Data) -> UIImage {
        // Runs on any thread, not MainActor
        ...
    }
}

---

3. Isolated Conformances

Isolated conformances let a `@MainActor` type conform to a protocol that does not require actor isolation, using `extension Type: @MainActor ProtocolName`. Before Swift 6.2, this produced a compiler error about the main actor-isolated conformance crossing an isolation boundary.

protocol Exportable {
    func export()
}

@MainActor
final class StickerModel {
    let processor: PhotoProcessor
    func doExport() { processor.exportAsPNG() }
}

// ✅ Swift 6.2 -- isolated conformance
extension StickerModel: @MainActor Exportable {
    func export() {
        processor.exportAsPNG()  // Works: conformance is MainActor-isolated
    }
}

The conformance can only be used from a context that shares the same isolation domain:

// ✅ Used within @MainActor context -- OK
@MainActor
func exportAll(_ items: [any Exportable]) {
    for item in items { item.export() }
}

// ❌ Used outside @MainActor -- compile error
nonisolated func exportAll(_ items: [any Exportable]) {
    for item in items {
        item.export()  // Error: isolated conformance not available here
    }
}

---

4. @concurrent -- Explicit Background Execution

`@concurrent` explicitly offloads a function to the background thread pool, replacing the pattern of using `Task.detached` for compute-intensive operations.

nonisolated struct ImageProcessor {
    @concurrent
    func resize(image: Data, to size: CGSize) async -> Data {
        // Runs on background thread pool
        ...
    }
}

// Caller (on MainActor):
let resized = await ImageProcessor().resize(image: data, to: targetSize)

Steps to Offload Work

1. Make the containing type `nonisolated` (for structs/classes; actors are already isolated) 2. Add `@concurrent` to the function 3. Make the function `async` 4. Callers use `await`

@concurrent vs Task.detached vs actor

| Mechanism | Use Case | Structured? | |-----------|----------|-------------| | `@concurrent` | Single function that must run on background thread | Yes (inherits task context) | | `Task.detached` | Fire-and-forget background work, no structured parent | No | | `actor` | Shared mutable state

Read more
Ships withrshankras-apple-skills

A collection of Claude Code skills for iOS, macOS, watchOS, visionOS, and Apple platform development. These skills help you plan and build apps, maintain code quality, ensure HIG compliance, and guide you from idea to App Store.

Get the whole plugin
Stats
603
Stars
51
Forks
Active
Maintenance
Swift
Language
MIT
License
16d ago
Last commit
9mo ago
Created

Repo: rshankras/claude-code-apple-skills

Other skills on rshankras-apple-skills.