skills/swift-concurrency-6-2/SKILL.md
Swift 6.2 易用的并发(Approachable Concurrency)—— 默认单线程,使用 @concurrent 进行显式后台卸载,针对主执行角色(Main Actor)类型的隔离一致性。
npx skillsauth add xu-xiang/everything-claude-code-zh swift-concurrency-6-2Install this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
采用 Swift 6.2 并发模型的模式:代码默认在单线程运行,并发需显式引入。在不牺牲性能的情况下消除常见的数据竞争(Data-race)错误。
MainActor 的应用架构MainActor 隔离的类型上实现协议一致性(Protocol conformances)在 Swift 6.1 及更早版本中,异步函数(Async functions)可能会被隐式卸载到后台线程,即使在看似安全的代码中也会导致数据竞争错误:
// Swift 6.1: 错误 (ERROR)
@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 }
// 错误:发送 'self.photoProcessor' 存在引起数据竞争的风险
return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier)
}
}
Swift 6.2 修复了这个问题:异步函数默认保留在调用方执行角色(Actor)上。
// Swift 6.2: 正常 (OK) — 异步保留在 MainActor,无数据竞争
@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)
}
}
MainActor 类型现在可以安全地遵守非隔离协议:
protocol Exportable {
func export()
}
// Swift 6.1: 错误 (ERROR) — 跨入主执行角色隔离的代码
// Swift 6.2: 正常 (OK),使用隔离一致性
extension StickerModel: @MainActor Exportable {
func export() {
photoProcessor.exportAsPNG()
}
}
编译器确保该一致性仅在主执行角色上使用:
// 正常 (OK) — ImageExporter 也是 @MainActor
@MainActor
struct ImageExporter {
var items: [any Exportable]
mutating func add(_ item: StickerModel) {
items.append(item) // 安全:相同的执行角色隔离
}
}
// 错误 (ERROR) — 非隔离上下文不能使用 MainActor 一致性
nonisolated struct ImageExporter {
var items: [any Exportable]
mutating func add(_ item: StickerModel) {
items.append(item) // 错误:此处无法使用 Main actor 隔离的一致性
}
}
使用 MainActor 保护全局/静态状态:
// Swift 6.1: 错误 (ERROR) — 非 Sendable 类型可能具有共享的可变状态
final class StickerLibrary {
static let shared: StickerLibrary = .init() // 错误
}
// 修复:添加 @MainActor 注解
@MainActor
final class StickerLibrary {
static let shared: StickerLibrary = .init() // 正常 (OK)
}
Swift 6.2 引入了一种默认推断 MainActor 的模式 —— 无需手动注解:
// 启用 MainActor 默认推断后:
final class StickerLibrary {
static let shared: StickerLibrary = .init() // 隐式为 @MainActor
}
final class StickerModel {
let photoProcessor: PhotoProcessor
var selection: [PhotosPickerItem] // 隐式为 @MainActor
}
extension StickerModel: Exportable { // 隐式为 @MainActor 一致性
func export() {
photoProcessor.exportAsPNG()
}
}
此模式为选填项,推荐用于 App、脚本和其他可执行目标。
当你需要真正的并行性时,使用 @concurrent 显式卸载:
重要提示: 此示例需要“易用的并发”构建设置 —— SE-0466(MainActor 默认隔离)和 SE-0461(默认非隔离且非发送)。启用这些设置后,
extractSticker会保留在调用方的执行角色上,从而使可变状态访问变得安全。如果没有这些设置,此代码将存在数据竞争 —— 编译器会对其报错。
nonisolated final class PhotoProcessor {
private 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 { /* ... */ }
}
// 调用方必须使用 await
let processor = PhotoProcessor()
processedPhotos[item.id] = await processor.extractSticker(data: data, with: item.id)
使用 @concurrent 的步骤:
nonisolated@concurrentasyncawait| 决策 | 原理 |
|----------|-----------|
| 默认单线程 | 大多数自然编写的代码都是无数据竞争的;并发是选填的 |
| 异步保留在调用执行角色上 | 消除导致数据竞争错误的隐式卸载 |
| 隔离一致性 | MainActor 类型可以遵守协议,而无需不安全的临时方案 |
| @concurrent 显式选填 | 后台执行是深思熟虑的性能选择,而非偶然 |
| MainActor 默认推断 | 减少 App 目标中冗余的 @MainActor 注解 |
| 选填式采用 | 非破坏性的迁移路径 —— 增量启用功能 |
SwiftSettings API@concurrent:先进行性能分析 (Profile),然后卸载热点路径@concurrent —— 图像处理、压缩、复杂计算nonisolated 临时方案或 @Sendable 包装器@concurrent(大多数函数不需要后台执行)nonisolated 来压制编译器错误DispatchQueue 模式model.availability 检查MainActor 为中心的应用架构(大多数 UI App)documentation
将签证申请文件(图像)翻译成英文,并创建包含原文和译文的双语 PDF。
development
Claude Code 会话的全方位验证系统。
tools
在编写新功能、修复 Bug 或重构代码时使用此技能。强制执行测试驱动开发(TDD),包括单元测试、集成测试和 E2E 测试,且覆盖率需达到 80% 以上。
tools
SwiftUI 架构模式,使用 @Observable 进行状态管理,视图组合、导航、性能优化以及现代 iOS/macOS UI 最佳实践。