All skills
johnrogers avatar

/modern-swift

@d62eb71

Use when writing async/await code, enabling strict concurrency, fixing Sendable errors, migrating from completion handlers, managing shared state with actors, or using Task/TaskGroup for concurrency.

Use this Skill: https://skilld.dev/gh/johnrogers/claude-swift-engineering/modern-swift

This session only. Nothing lands on disk.

referencesconcurrency-essentials.md

≈864 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Concurrency Essentials

Core patterns for async/await, @MainActor, actors, and Sendable in Swift 6.2.

Start Single-Threaded First

Apple Guidance (WWDC 2025): "Start by running all code on the main thread."

When to add complexity:

  1. Stay single-threaded if UI is responsive (<16ms per frame)
  2. Add async/await when network/file I/O would block UI
  3. Add concurrency when CPU work freezes UI (profile first!)
  4. Add actors when main actor contention causes bottlenecks

Concurrent code is more complex. Only introduce it when profiling proves it's needed.

Async/Await — NOT Completion Handlers

✅ Modern Pattern

func fetchUser(id: String) async throws -> User {
    let (data, _) = try await URLSession.shared.data(from: url)
    return try JSONDecoder().decode(User.self, from: data)
}

// Calling async functions
Task {
    let user = try await fetchUser(id: "123")
}

❌ Deprecated Pattern

// NEVER use completion handlers
func fetchUser(id: String, completion: @escaping (Result<User, Error>) -> Void) {
    URLSession.shared.dataTask(with: url) { data, _, error in
        // ...
    }.resume()
}

@MainActor — NOT DispatchQueue.main

✅ Modern Pattern

@MainActor
class ViewModel: ObservableObject {
    var items: [Item] = []

    func loadItems() async {
        // Already on main actor — UI updates are safe
        items = try await fetchItems()
    }
}

// Or for individual properties
class Service {
    @MainActor var uiState: UIState = .idle
}

❌ Deprecated Pattern

// NEVER use DispatchQueue.main.async
DispatchQueue.main.async {
    self.items = newItems
}

Actor Isolation — NOT Locks

✅ Modern Pattern

actor DatabaseManager {
    private var cache: [String: Data] = [:]

    func getData(key: String) -> Data? {
        cache[key]
    }

    func setData(_ data: Data, key: String) {
        cache[key] = data
    }
}

// Usage
let data = await database.getData(key: "user")

❌ Deprecated Pattern

// NEVER use locks or serial queues
class DatabaseManager {
    private let queue = DispatchQueue(label: "db")
    private var cache: [String: Data] = [:]

    func getData(key: String) -> Data? {
        queue.sync { cache[key] }
    }
}

Sendable — Thread-Safe Types

✅ Conforming to Sendable

// Value types are implicitly Sendable
struct User: Sendable {
    let id: String
    let name: String
}

// Actors are implicitly Sendable
actor UserCache { }

// Classes require @unchecked Sendable (use sparingly)
final class ImmutableConfig: @unchecked Sendable {
    let apiKey: String
    let baseURL: URL

    init(apiKey: String, baseURL: URL) {
        self.apiKey = apiKey
        self.baseURL = baseURL
    }
}

❌ Common Errors

// ERROR: Non-Sendable type crossing actor boundary
class MutableState { var count = 0 }

actor Counter {
    // ❌ MutableState is not Sendable
    func update(state: MutableState) { }
}

Common Patterns

Network Request

func loadData() async throws -> Data {
    try await URLSession.shared.data(from: url).0
}

Background Work + UI Update

@MainActor
func refresh() async {
    let data = await Task.detached {
        // Heavy computation off main actor
        await processData()
    }.value

    // Back on main actor automatically
    self.items = data
}

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill is a comprehensive and safe reference guide for modern Swift 6 concurrency patterns, providing standard examples and migration guidelines with no security risks detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer7mo

    9 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at d62eb71. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Dormantupdated 9 months ago

README badge

README badge for johnrogers/claude-swift-engineering/modern-swift