AgentSkillsCN

swift-concurrency

掌握 Swift 并发编程模式,包括 Actor、async/await 以及 AsyncStream。

SKILL.md
--- frontmatter
name: swift-concurrency
description: Swift Concurrency patterns with Actors, async/await, and AsyncStream

Swift Concurrency Skill

Overview

Modern Swift concurrency patterns using Actors, async/await, and AsyncStream for thread-safe, reactive programming.

Actors for Thread-Safety

Why Actors over Locks?

AspectNSLockActor
SafetyRuntime crash if forgottenCompile-time guarantee
Deadlock RiskManual preventionImpossible
Async IntegrationAwkwardNative

Actor Pattern

swift
public actor CartStore {
    private var carts: [CartOwner: Cart] = [:]
    
    public func get(owner: CartOwner) -> Cart {
        carts[owner] ?? Cart.empty(owner: owner)
    }
    
    public func upsert(_ cart: Cart) {
        carts[cart.owner] = cart
        notifyContinuations(cart)
    }
}

Actor Isolation Rules

swift
// ❌ Cannot access actor property synchronously
let cart = cartStore.carts["user"]

// ✅ Must await actor method
let cart = await cartStore.get(owner: "user")

AsyncStream for Observation

Stream Pattern

swift
public actor Store {
    private var continuations: [UUID: AsyncStream<State>.Continuation] = [:]
    
    public func stream() -> AsyncStream<State> {
        AsyncStream { continuation in
            let id = UUID()
            self.continuations[id] = continuation
            
            // Yield current state
            continuation.yield(self.state)
            
            // Cleanup on termination
            continuation.onTermination = { _ in
                Task { await self.removeContinuation(id) }
            }
        }
    }
    
    private func removeContinuation(_ id: UUID) {
        continuations.removeValue(forKey: id)
    }
    
    private func notifyContinuations(_ state: State) {
        for continuation in continuations.values {
            continuation.yield(state)
        }
    }
}

Consuming Streams

swift
// In ViewModel
Task {
    for await cart in repository.stream() {
        self.items = cart.items
    }
}

Structured Concurrency

Task Management

swift
public actor SyncWorker {
    private var task: Task<Void, Never>?
    
    public func start() {
        task = Task {
            while !Task.isCancelled {
                await processNextOperation()
                try? await Task.sleep(nanoseconds: 1_000_000_000)
            }
        }
    }
    
    public func stop() {
        task?.cancel()
        task = nil
    }
}

Common Patterns

Exponential Backoff

swift
func processWithRetry(_ operation: Operation) async {
    let backoff = min(pow(2, Double(operation.attempts + 1)) * 0.6, 8.0)
    try? await Task.sleep(nanoseconds: UInt64(backoff * 1_000_000_000))
    await retry(operation)
}

MainActor for UI

swift
@MainActor
public final class ViewModel: ObservableObject {
    @Published var items: [Item] = []
    
    // Automatically runs on main thread
    func updateUI() {
        items = newItems
    }
}

Anti-Patterns

swift
// ❌ Blocking main thread
Task {
    let result = await heavyWork()  // Don't do heavy work on main
}

// ✅ Offload to background
Task.detached {
    let result = await heavyWork()
    await MainActor.run { updateUI(result) }
}