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.

referencestask-cancellation.md

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

Task Cancellation

Cooperative cancellation patterns in Swift 6.2 structured concurrency.

Cooperative Model

Swift tasks use cooperative cancellation:

  • Cancellation is requested, not forced
  • Tasks must check for cancellation and respond
  • No automatic interruption

checkCancellation vs isCancelled

Task.checkCancellation()

Throws CancellationError if cancelled. Use in throwing contexts.

func processItems(_ items: [Item]) async throws {
    for item in items {
        try Task.checkCancellation()
        await process(item)
    }
}

Task.isCancelled

Returns Bool. Use for graceful cleanup in non-throwing contexts.

func processItems(_ items: [Item]) async {
    for item in items {
        if Task.isCancelled {
            print("Cancelled, stopping early")
            return
        }
        await process(item)
    }
}

withTaskCancellationHandler

Runs cleanup when task is cancelled.

func downloadFile(url: URL) async throws -> Data {
    let download = URLSession.shared.dataTask(with: url)

    return try await withTaskCancellationHandler {
        try await download.value
    } onCancel: {
        download.cancel()
    }
}

Cancellation Patterns

Long-Running Loop

func monitorEvents() async throws {
    while !Task.isCancelled {
        let event = try await fetchNextEvent()
        try Task.checkCancellation()
        await handle(event)
    }
}

TaskGroup with Cancellation

func fetchWithTimeout(ids: [String]) async throws -> [User] {
    try await withThrowingTaskGroup(of: User.self) { group in
        // Add tasks
        for id in ids {
            group.addTask {
                try await fetchUser(id: id)
            }
        }

        // Cancel all if one fails
        var users: [User] = []
        do {
            for try await user in group {
                users.append(user)
            }
        } catch {
            group.cancelAll()
            throw error
        }
        return users
    }
}

Timeout Pattern

func withTimeout<T>(
    seconds: TimeInterval,
    operation: @escaping @Sendable () async throws -> T
) async throws -> T {
    try await withThrowingTaskGroup(of: T.self) { group in
        group.addTask {
            try await operation()
        }

        group.addTask {
            try await Task.sleep(for: .seconds(seconds))
            throw TimeoutError()
        }

        let result = try await group.next()!
        group.cancelAll()
        return result
    }
}

Best Practices

  1. Check frequently in loops and long operations
  2. Propagate cancellation to child tasks
  3. Clean up resources in cancellation handlers
  4. Don't ignore cancellation - respond appropriately
  5. Use checkCancellation() in throwing code for cleaner errors

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