swift-concurrency
Skill1 starsChanged 7 months agoMITView on GitHub
Use when writing concurrent Swift code — actors, Sendable, AsyncSequence, task cancellation, synchronization, state machines, reactive patterns, generics, testing, and diagnostics. Targets Swift 6 strict concurrency.
25 other projects use a version of this.
Adopted by
Most recently taken up by
- tornikegomareli/Skillstheir own version, first seen Nov 8, 2026
- uinaf/slopwaketheir own version, first seen Nov 3, 2026
- igorkulman/pi-skillstheir own version, first seen Nov 1, 2026
- VelimirMueller/claude-skillstheir own version, first seen Nov 1, 2026
- VelimirMueller/ai-development-skillstheir own version, first seen Nov 1, 2026
- The-Artificer-of-Ciphers-LLC/skills-from-the-artificertheir own version, first seen Nov 1, 2026
Used with
Projects with it also use swiftdata, swiftui-expert-skill and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
Prisma-Labs-DevSkillswiftdata
API reference: SwiftData. Query for @Model, ModelContext, @Query, schema migrations.
Also in 3 projects that use this
xfstudioSkillswiftui-expert-skill
Write, review, or improve SwiftUI code following best practices for state management, view composition, performance, modern APIs, Swift concurrency, and iOS 26+ Liquid Glass adoption. Use when building new SwiftUI features, refactoring existing views, reviewing code quality, or adopting modern SwiftUI patterns.
Also in 8 projects that use this
pluginagentmarketplaceSkillswift-testing
Test Swift applications - XCTest, Swift Testing, UI tests, mocking, TDD, CI/CD
Also in 4 projects that use this
eugenepyvovarovSkillswift-concurrency-expert
Swift Concurrency review and remediation for Swift 6.2+. Use when asked to review Swift Concurrency usage, improve concurrency compliance, or fix Swift concurrency compiler errors in a feature or file.
Also in 4 projects that use this
AvdLeeSkillswift-testing-expert
Expert guidance for Swift Testing: test structure, #expect/#require macros, traits and tags, parameterized tests, test plans, parallel execution, async waiting patterns, and XCTest migration. Use when writing new Swift tests, modernizing XCTest suites, debugging flaky tests, or improving test quality and maintainability in Apple-platform or Swift server projects.
Also in 3 projects that use this
dadederkSkillios-accessibility
Expert guidance on iOS accessibility best practices, patterns, and implementation. Use when developers mention: (1) iOS accessibility, VoiceOver, Dynamic Type, or assistive technologies, (2) accessibility labels, traits, hints, or values, (3) automated accessibility testing, auditing, or manual testing, (4) Switch Control, Voice Control, or Full Keyboard Access, (5) inclusive design or accessibility culture, (6) making apps work for users with disabilities.
Also in 3 projects that use this
Other versions25 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 25
- Provenance-Emu/Provenance★ 6.4ksame name
- pluk-inc/markdown-preview★ 2.8ksame name
- pluk-inc/md-preview.app★ 2.8ksame name
- AvdLee/Swift-Concurrency-Agent-Skill★ 1.7ksame name
- AFK-surf/OpenBridge★ 430same name
- Prisma-Labs-Dev/apple-skills★ 336same name
- jamesrochabrun/skills★ 209same name
- pepicrft/fuckingapproachableswiftconcurrency★ 156same name
- wendylabsinc/claude-skills★ 62same name
- nonameplum/agent-skills★ 17same name
15 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository12 other files it gives its agents.
- advanced-swift-patternsSkill
- apotheneum-patternSkill
- githubSkill
- idea-framingSkill
- metal-graphicsSkill
- realitykit-visionosSkill
- sonic-piSkill
- strudelSkill
- swiftui-architectureSkill
- te-patternSkill
- te-shaderSkill
- te-showSkill
The file
We split this skill into the rules it gives an agent
7 rules. 0 are common, 2 are distinctive, and 5 are very specific to this project.
0
Common
Most of the 24 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 28
All shared data types conform to Sendable
- Distinctive: line 31
No data races detected by compiler
- Very specific: line 294
Check Task.isCancelled before updating state
- Very specific: line 295
Use [weak self] in Task closures
- Very specific: line 427
Use descriptive case names (.invalidURL not .error1)
- Very specific: line 431
Never use generic NSError in new code
- Distinctive: line 788
Start with most restrictive access level.
“Common” is measured: kept by at least 6 in 10 of the 24 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Swift Concurrency & Patterns Reference
Swift 6 Strict Concurrency
Configuration
// Package.swift
swiftSettings: [
.enableUpcomingFeature("StrictConcurrency")
]// Xcconfig
SWIFT_VERSION = 6.0
SWIFT_STRICT_CONCURRENCY = complete
SWIFT_TREAT_WARNINGS_AS_ERRORS = YESThread-Safety Checklist
- All shared data types conform to
Sendable - Mutable state protected by actors or synchronization primitives
- Closures marked with
@Sendablewhen crossing concurrency boundaries - No data races detected by compiler
Actor Patterns
Standard Actor
actor DataProcessor {
private var state: ProcessingState = .idle
private var subscriptions = [UUID: Subscription]()
nonisolated let identifier: UUID // Safe cross-actor access
func process(_ data: Data) async throws -> Result {
// Automatically isolated to this actor
}
}Actor Service (Preferred for Services)
actor APIService {
private let session: URLSession
init() {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 60.0
self.session = URLSession(configuration: config)
}
func fetchData() async throws -> [Item] {
let (data, _) = try await session.data(for: request)
return try JSONDecoder().decode([Item].self, from: data)
}
}Isolation Context Propagation
protocol ServiceDelegate: Sendable {
func serviceDidUpdate(
isolation: isolated (any Actor)?,
value: SomeValue
) async
}Safe Delegation in Actors
actor Service {
private nonisolated(unsafe) weak var _delegate: Delegate?
private var delegate: Delegate {
get throws {
guard let _delegate else {
throw ServiceError.delegateUnavailable
}
return _delegate
}
}
func notifyDelegate() async throws {
try await delegate.serviceDidUpdate(self)
}
}Sendable Conformance
Structs (Preferred)
struct DataModel: Codable, Identifiable, Hashable, Sendable {
let id: UUID
let name: String
let timestamp: Date
// All properties must be Sendable types
}Sendable-Compatible Types
- Primitive types:
String,Int,Bool,Double,Float - Standard library:
Date,URL,UUID,Data - Collections of Sendable:
[String],[Int: String] - Enums with Sendable associated values
- Other Sendable structs
Classes with Manual Thread Safety
final class ThreadSafeCache: @unchecked Sendable {
private let lock = NSLock()
private var cache: [String: Data] = [:]
func get(_ key: String) -> Data? {
lock.lock()
defer { lock.unlock() }
return cache[key]
}
func set(_ key: String, value: Data) {
lock.lock()
defer { lock.unlock() }
cache[key] = value
}
}Non-Sendable Third-Party Libraries
@preconcurrency import ThirdPartyLib
@preconcurrency import AVFoundation
@preconcurrency import FirebaseFirestoreAsyncSequence & AsyncStream
AsyncThrowingStream for Progress
func export() -> AsyncThrowingStream<ExportEvent, Error> {
AsyncThrowingStream { continuation in
Task {
do {
for progress in stride(from: 0.0, through: 1.0, by: 0.1) {
try Task.checkCancellation()
continuation.yield(.progress(Float(progress)))
}
continuation.yield(.completed(outputURL))
continuation.finish()
} catch {
continuation.finish(throwing: error)
}
}
}
}
// Consumption
for try await update in service.export() {
switch update {
case .progress(let value): print("Progress: \(value)")
case .completed(let url): print("Done: \(url)")
}
}AsyncStream for Real-Time Updates (Firebase, Location, etc.)
func observeChanges(id: String) -> AsyncStream<[Item]> {
AsyncStream { continuation in
let listener = database.collection("items")
.document(id)
.addSnapshotListener { snapshot, error in
guard let snapshot = snapshot else { return }
let items = snapshot.documents.compactMap { doc in
try? Item(from: doc.data())
}
continuation.yield(items)
}
continuation.onTermination = { _ in
listener.remove() // Clean up listener
}
}
}AsyncNotifier (Multi-Subscriber Broadcast)
final class AsyncNotifier<Value: Sendable>: Sendable {
private struct State {
var continuations: [UUID: AsyncStream<Value>.Continuation] = [:]
var currentValue: Value?
}
private let state = OSAllocatedUnfairLock(initialState: State())
func yield(_ value: Value) {
let continuations = state.withLock { state in
state.currentValue = value
return Array(state.continuations.values)
}
for continuation in continuations {
continuation.yield(value)
}
}
var sequence: AsyncStream<Value> {
let (stream, continuation) = AsyncStream<Value>.makeStream()
let id = UUID()
state.withLock { state in
state.continuations[id] = continuation
if let current = state.currentValue {
continuation.yield(current)
}
}
continuation.onTermination = { [weak self] _ in
self?.state.withLock { state in
state.continuations[id] = nil
}
}
return stream
}
}AsyncBroadcastChannel
final class AsyncBroadcastChannel<Element: Sendable>: Sendable, AsyncSequence {
func makeAsyncIterator() -> AsyncIterator { /* ... */ }
func broadcast(_ element: Element) async { /* ... */ }
}Task Cancellation & Resource Management
@MainActor
final class ViewModel: ObservableObject {
@Published var isLoading = false
private var loadingTask: Task<Void, Never>?
deinit {
loadingTask?.cancel() // Prevent memory leaks
}
func startLoading() {
loadingTask?.cancel() // Cancel previous
loadingTask = Task { @MainActor [weak self] in
guard let self, !Task.isCancelled else { return }
do {
let result = try await service.fetchData()
guard !Task.isCancelled else { return }
self.data = result
} catch {
guard !Task.isCancelled else { return }
self.errorMessage = error.localizedDescription
}
}
}
}Cancellation Checklist
- Store long-running tasks as properties
- Cancel tasks in
deinit - Check
Task.isCancelledbefore updating state - Use
[weak self]in Task closures - Cancel previous tasks before starting new ones
- Invalidate timers in deinit
Synchronization Primitives
Mutex (Preferred for Simple State)
import Synchronization
final class StateContainer: @unchecked Sendable {
private let state = Mutex<State>()
struct State {
var pending: [Job] = []
var active: Job?
}
func enqueue(_ job: Job) {
state.withLock { $0.pending.append(job) }
}
func dequeue() -> Job? {
state.withLock { $0.pending.isEmpty ? nil : $0.pending.removeFirst() }
}
}Selection Criteria
| Need | Use |
| Complex stateful objects | actor |
| Simple value protection | Mutex |
| Low-level synchronization | OSAllocatedUnfairLock |
| Avoid manual locking when possible | actor |
State Machines
actor StateMachine<State: Hashable, Event: Hashable> {
private(set) var currentState: State
private var transitions: [State: [Event: State]]
init(initial: State) {
self.currentState = initial
self.transitions = [:]
}
func addTransition(from: State, on: Event, to: State) {
transitions[from, default: [:]][on] = to
}
func execute(_ event: Event) -> Bool {
guard let next = transitions[currentState]?[event] else { return false }
currentState = next
return true
}
}Reactive Patterns
AsyncNotifying Protocol
protocol AsyncNotifying: Sendable {
associatedtype Value: Sendable
var value: Value { get async }
func subscribe(
receiveValue: @escaping @isolated(any) @Sendable (_ newValue: Value) async -> ()
) -> Subscription
}Reactive Property Wrapper
@propertyWrapper
struct UserDefault<Value: Codable> {
let key: String
let defaultValue: Value
var wrappedValue: Value { get set }
var projectedValue: AsyncStream<Value> { get } // Observe changes
}Error Handling
Domain-Specific LocalizedError
enum NetworkError: LocalizedError, Sendable {
case connectionFailed(reason: String)
case timeout(duration: TimeInterval)
case invalidResponse(statusCode: Int)
var errorDescription: String? {
switch self {
case .connectionFailed(let reason):
return "Connection failed: \(reason)"
case .timeout(let duration):
return "Request timed out after \(duration)s"
case .invalidResponse(let code):
return "Invalid response: HTTP \(code)"
}
}
var recoverySuggestion: String? {
switch self {
case .timeout:
return "Check your network connection and try again"
default:
return nil
}
}
}Error Handling Best Practices
- Define errors in the same file as the service
- Handle at ViewModel layer, not in Views
- Use descriptive case names (
.invalidURLnot.error1) - Include context via associated values
- User-friendly messages in
errorDescription - Make all error enums
Sendable - Never use generic
NSErrorin new code
Data Persistence
Generic Record Store
protocol RecordStore: Sendable {
associatedtype Record: Sendable
func record(for key: String) async -> Record?
func allRecords() async -> [String: Record]
func store(_ record: Record, for key: String) async
func delete(key: String) async
}Type-Safe File I/O
final class DiskIO<T: Codable>: Sendable {
let fileURL: URL
let protectionType: FileProtectionType
func read() async throws -> T
func write(_ value: T) async throws
func delete() async throws
var changes: AsyncStream<T> { get }
}Networking & Flow Control
Rate Limiting (Token Bucket)
actor RateLimiter {
let capacity: Int
let refillRate: TimeInterval
private var tokens: Double
private var lastRefill: Date
func allowRequest() async -> Bool {
let now = Date()
let elapsed = now.timeIntervalSince(lastRefill)
tokens = min(Double(capacity), tokens + elapsed / refillRate)
lastRefill = now
guard tokens >= 1 else { return false }
tokens -= 1
return true
}
}Back-Pressure
final class BackPressureChannel<Element: Sendable>: AsyncSequence {
func send(_ element: Element) async {
// Suspends until consumers process the value
}
}Generics & Type Safety
Generic Constraints
protocol DataTransformer {
associatedtype Input
associatedtype Output
func transform(_ input: Input) async throws -> Output
}
extension DataTransformer where Input: Codable, Output: Codable {
func transformAndSerialize(_ input: Input) async throws -> Data {
let output = try await transform(input)
return try JSONEncoder().encode(output)
}
}Type Erasure
struct AnyDataProvider<Element: Sendable>: DataProvider {
private let _start: @Sendable () async throws -> Void
private let _elements: @Sendable () async -> AsyncStream<Element>
init<P: DataProvider>(_ provider: P) where P.Element == Element {
_start = provider.start
_elements = { await provider.elements }
}
}Type Aliases for Domain Clarity
typealias UserIdentifier = String
typealias SessionToken = String
typealias Timestamp = UInt64IPC (Inter-Process Communication)
protocol Message: Sendable, Codable {
associatedtype Reply: Sendable, Codable
}
protocol IPCInterface {
associatedtype ClientMessages: MessagesProtocol
associatedtype HostMessages: MessagesProtocol
}Testing Patterns
Async Testing
final class ServiceTests: XCTestCase {
var sut: SystemUnderTest!
var mockDependency: MockDependency!
override func setUp() async throws {
mockDependency = MockDependency()
sut = SystemUnderTest(dependency: mockDependency)
}
override func tearDown() async throws {
await sut.cleanup()
sut = nil
}
func testFeatureBehavior() async throws {
// Arrange
mockDependency.configureResponse(.success)
// Act
let result = try await sut.performAction()
// Assert
XCTAssertEqual(result, expectedValue)
XCTAssertTrue(mockDependency.methodWasCalled)
}
}Cancellation Testing
func testCancellation() async throws {
let task = Task { try await service.longRunningWork() }
try await Task.sleep(nanoseconds: 100_000_000)
task.cancel()
do {
_ = try await task.value
XCTFail("Should have been cancelled")
} catch is CancellationError {
// Expected
}
}Async Sequence Test Iterator
actor AsyncSequenceTestIterator<S: AsyncSequence> {
func waitForNext(timeout: Duration = .seconds(1)) async throws -> S.Element
func assertRemainsEmpty(for duration: Duration) async throws
func finish() async
}Mock Guidelines
- Complete protocol implementations
- Configurable behavior (success/failure modes)
- Capture method calls for verification
- Support async/await patterns
Test Organization
Tests/
├── Unit/ # Isolated component tests
├── Integration/ # Multi-component tests
├── Mocks/ # Mock implementations
└── Utilities/ # Test helpers and assertionsLogging & Diagnostics
Unified Logging
import OSLog
extension Logger {
static let networking = Logger(subsystem: "com.app", category: "networking")
static let storage = Logger(subsystem: "com.app", category: "storage")
static let services = Logger(subsystem: "com.app", category: "services")
}
// Usage
Logger.networking.info("Request started: \(url)")
Logger.networking.error("Request failed: \(error)")Performance Monitoring
import OSLog
let signposter = OSSignposter(logger: Logger.performance)
func performCriticalOperation() async {
let state = signposter.beginInterval("CriticalOperation")
defer { signposter.endInterval("CriticalOperation", state) }
// Operation
}Service-Oriented Architecture
Protocol-Based Services
protocol ServiceProtocol: Sendable {
func stop() async
}
actor ServiceManager {
static let shared = ServiceManager()
private var services: [String: any ServiceProtocol] = [:]
func register<T: ServiceProtocol>(_ service: T, for key: String) {
services[key] = service
}
func service<T: ServiceProtocol>(for key: String) -> T? {
services[key] as? T
}
}Provider Pattern
protocol DataProvider: Sendable {
associatedtype Element: Sendable
var state: ProviderState { get async }
var elements: AsyncStream<Element> { get async }
func start() async throws
func pause() async
func resume() async
func stop() async
}
enum ProviderState: Sendable {
case initialized, running, paused, stopped
}CLI Tools
import ArgumentParser
@main
struct CLI: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "tool",
abstract: "A utility for managing the framework",
subcommands: [Start.self, Stop.self, Status.self]
)
}
struct Start: AsyncParsableCommand {
@Option(help: "Configuration file path")
var config: String?
@Flag(help: "Enable verbose output")
var verbose = false
mutating func run() async throws { }
}Documentation Standards
DocC Format
/// Performs an asynchronous operation with retry logic.
///
/// - Parameters:
/// - operation: The async operation to perform
/// - maxRetries: Maximum number of retry attempts
/// - Returns: The result of the operation
/// - Throws: The last error encountered if all retries fail
///
/// ## Example
/// ```swift
/// let result = try await performWithRetry { try await fetchData() }
/// ```
func performWithRetry<T>(
operation: @Sendable () async throws -> T,
maxRetries: Int = 3
) async throws -> TCode Organization
// MARK: - Lifecycle
init() { }
// MARK: - Public API
public func performAction() async throws { }
// MARK: - Private Implementation
private func helperMethod() { }
// MARK: - Protocol Conformance
extension MyClass: SomeProtocol { }Access Control
| Level | Use |
public | Framework API surface |
package | Shared between framework targets |
internal | Default, implementation details |
private | Narrowest scope possible |
Start with most restrictive access level. Expand only when necessary.
Build Configuration
Xcconfig Structure
Configs/
├── Base.xcconfig # Shared settings
├── Framework.xcconfig # Framework-specific
├── Tests.xcconfig # Test target settings
└── Tools.xcconfig # CLI toolsBase Settings
SWIFT_VERSION = 6.0
SWIFT_STRICT_CONCURRENCY = complete
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES
GCC_TREAT_WARNINGS_AS_ERRORS = YES
CLANG_ANALYZER_NONNULL = YES
CLANG_STATIC_ANALYZER_MODE = deep
ENABLE_TESTABILITY = YES
CLANG_ENABLE_MODULES = YESDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

