Agent skills for iOS, iPadOS, Swift, SwiftUI, and modern Apple framework development.
71
89%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
Approachable concurrency patterns introduced in Swift 6.2+ — a philosophy shift where code stays single-threaded by default until you choose to introduce concurrency.
@concurrent AttributeIn Swift 6.0/6.1, data-race safety was enforced at compile time, but the most natural code to write often produced data-race errors. Async functions on types with mutable state would implicitly hop to the global concurrent executor, causing send-safety violations even when no actual parallelism was intended.
// Swift 6.0/6.1: This produces a data-race error
class PhotoProcessor {
func extractSticker(data: Data, with id: String?) async -> Sticker? { /* ... */ }
}
@MainActor
final class StickerModel {
let photoProcessor = PhotoProcessor()
func extractSticker(_ item: PhotosPickerItem) async throws -> Sticker? {
guard let data = try await item.loadTransferable(type: Data.self) else { return nil }
// Error: Sending 'self.photoProcessor' risks causing data races
return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier)
}
}// Swift 6.2: The same code compiles without error
// because extractSticker stays on the caller's actor
class PhotoProcessor {
func extractSticker(data: Data, with id: String?) async -> Sticker? { /* ... */ }
}
@MainActor
final class StickerModel {
let photoProcessor = PhotoProcessor()
func extractSticker(_ item: PhotosPickerItem) async throws -> Sticker? {
guard let data = try await item.loadTransferable(type: Data.self) else { return nil }
return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier)
}
}Enable with the -default-isolation MainActor compiler flag or the Xcode 26
"Approachable Concurrency" build setting.
What it does:
@MainActor unless opted out.@MainActor.Recommended for: Apps, scripts, and executable targets. Not recommended for library targets that should remain actor-agnostic.
// With default MainActor isolation -- no @MainActor annotations needed:
final class StickerLibrary {
static let shared = StickerLibrary()
}
final class StickerModel {
let photoProcessor = PhotoProcessor()
var selection: [PhotosPickerItem] = []
}
extension StickerModel: Exportable {
func export() { photoProcessor.exportAsPNG() }
}Nonisolated async functions stay on the caller's actor by default instead of
hopping to the global concurrent executor. This is the nonisolated(nonsending)
default behavior.
Key implication: Values passed into an async function are never sent outside the actor, eliminating data races without annotation.
To explicitly opt into background execution, use @concurrent.
@concurrent AttributeEnsures a function always runs on the concurrent thread pool, freeing the calling actor for other work.
class PhotoProcessor {
var cachedStickers: [String: Sticker] = [:]
func extractSticker(data: Data, with id: String) async -> Sticker {
if let sticker = cachedStickers[id] { return sticker }
let sticker = await Self.extractSubject(from: data)
cachedStickers[id] = sticker
return sticker
}
@concurrent
static func extractSubject(from data: Data) async -> Sticker { /* ... */ }
}Steps to offload a function to background:
nonisolated (or the function itself).@concurrent to the function.async if not already asynchronous.await at call sites.nonisolated struct PhotoProcessor {
@concurrent
func process(data: Data) async -> ProcessedPhoto? { /* ... */ }
}
processedPhotos[item.id] = await PhotoProcessor().process(data: data)Task.immediate starts executing synchronously on the current actor before any
suspension point, rather than being enqueued. There is also
Task.immediateDetached which combines immediate start with detached semantics.
Task.immediate { await handleUserInput() }Use for latency-sensitive work where enqueue delay is unacceptable.
A conformance that needs MainActor state is called an isolated conformance. The compiler ensures the conformance is only used in a matching isolation context.
protocol Exportable {
func export()
}
extension StickerModel: @MainActor Exportable {
func export() { photoProcessor.exportAsPNG() }
}
@MainActor
struct ImageExporter {
var items: [any Exportable]
mutating func add(_ item: StickerModel) {
items.append(item) // OK -- on MainActor
}
}
// But in a nonisolated context:
nonisolated struct GenericExporter {
var items: [any Exportable]
mutating func add(_ item: StickerModel) {
// Error: Main actor-isolated conformance of 'StickerModel' to
// 'Exportable' cannot be used in nonisolated context
items.append(item)
}
}Immutable weak references (weak let) enable Sendable conformance for types
that hold weak references, since immutability guarantees thread safety. Proposed
in SE-0481; may not yet be available in shipping toolchains.
Observations { } provides transactional observation of @Observable types
via AsyncSequence.
for await _ in Observations { model.count } {
print("Count changed to \(model.count)")
}Global and static variables are prone to data races. The most common protection
is @MainActor:
@MainActor
final class StickerLibrary {
static let shared = StickerLibrary() // protected by MainActor
}With default MainActor isolation (SE-0466), this annotation is implicit.
All approachable concurrency features are opt-in via:
swiftSettings in Package.swift using the SwiftSetting API.Swift 6.2 includes migration tooling to help make necessary code changes automatically. See swift.org/migration for details.
The Swift 6.2 concurrency progression:
@concurrent.skills
accessorysetupkit
references
activitykit
references
adattributionkit
references
alarmkit
references
app-clips
app-intents
references
app-store-optimization
app-store-review
apple-on-device-ai
appmigrationkit
references
audioaccessorykit
references
authentication
references
avkit
references
background-processing
references
browserenginekit
references
callkit
references
carplay
references
cloudkit
references
contacts-framework
references
core-bluetooth
references
core-data
core-motion
references
core-nfc
references
coreml
references
cryptokit
references
cryptotokenkit
references
debugging-instruments
device-integrity
references
dockkit
references
energykit
references
eventkit
references
financekit
references
focus-engine
gamekit
references
healthkit
references
homekit
references
ios-accessibility
ios-localization
ios-networking
ios-simulator
references
mapkit
metrickit
references
musickit
references
natural-language
references
paperkit
references
passkit
references
pdfkit
references
pencilkit
references
permissionkit
references
photokit
push-notifications
realitykit
references
relevancekit
references
scenekit
references
sensorkit
references
speech-recognition
spritekit
references
storekit
swift-api-design-guidelines
swift-architecture
swift-charts
references
swift-codable
swift-concurrency
swift-formatstyle
swift-language
swift-security
references
swift-testing
swiftdata
swiftlint
swiftui-animation
swiftui-gestures
references
swiftui-layout-components
swiftui-liquid-glass
references
swiftui-patterns
swiftui-performance
swiftui-uikit-interop
swiftui-webkit
tabletopkit
references
tipkit
references
vision-framework
weatherkit
references
widgetkit
references