mcpField
S
swift-best-practices

swift-best-practices

github.com/sammcj开发16987 次安装4 天前更新
代码仓库

关于 swift-best-practices

swift-best-practices 是面向 iOS 和 macOS 开发者的 Swift 编码指导技能,适用于编写、审查或迁移代码,重点涵盖 Swift 6 并发安全、API 设计和代码质量。

主要功能

  1. 01Swift 6 并发与隔离指导
  2. 02async/await 和取消处理实践
  3. 03API 命名与参数标签规范
  4. 04可用性标注和迁移指导
  5. 05深入主题的参考资料

适用场景

  1. 01编写 iOS 或 macOS 的 Swift 代码
  2. 02审查并发安全与 Actor 隔离
  3. 03将项目从 Swift 5 迁移到 Swift 6
  4. 04解决 Sendable 和隔离问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sammcj/agentic-coding --skill swift-best-practices

安装后在 Claude Code 中输入/swift-best-practices确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
api-design.md
availability-patterns.md
concurrency.md
swift6-features.md

详细介绍

Swift 最佳实践技能

概述

针对以 macOS 15.7+ 为目标的 iOS 和 macOS 项目,应用现代 Swift 开发最佳实践,重点关注 Swift 6+ 特性、并发安全、API 设计原则和代码质量指南。

何时使用此技能

在以下情况下使用此技能:

  • 为 iOS 或 macOS 应用编写新的 Swift 代码
  • 检查 Swift 代码的正确性、安全性和风格
  • 实现 Swift 并发特性(async/await、actors、MainActor)
  • 设计 Swift API 和公共接口
  • 将代码从 Swift 5 迁移到 Swift 6
  • 处理与 Sendable/隔离相关的并发警告、数据竞争问题或编译器错误
  • 使用 Swift 6 和 6.2 引入的现代 Swift 语言特性

核心指南

基本原则
  1. 使用时的清晰度至关重要——应通过检查用例而非仅看声明来评估设计
  2. 清晰胜于简洁——紧凑的代码应来自类型系统,而非尽量减少字符
  3. 为每个公共声明编写文档——如果无法简单描述其功能,该 API 可能设计不佳
  4. 按角色而非类型命名——使用 var greeting = "Hello",而非 var string = "Hello"
  5. 以简洁实现优雅——除非复杂性确有必要,否则避免过度设计
Swift 6 并发模型

Swift 6 默认启用完整的并发检查,并采用基于区域的隔离(SE-0414)。编译器现在可以证明代码安全性,在编译时消除许多误报,同时捕获真实的并发问题。

关键认知:

  • 异步 ≠ 后台——异步函数可以暂停,但不会自动在后台线程上运行
  • Actors 通过自动同步保护可变的共享状态
  • @MainActor 确保与 UI 相关的代码在主线程上执行
  • 全局 Actor 隔离类型会自动符合 Sendable
必备模式
Async/Await
// Parallel execution with async let
func fetchData() async -> (String, Int) {
    async let stringData = fetchString()
    async let intData = fetchInt()
    return await (stringData, intData)
}

// Always check cancellation in long-running operations
func process(_ items: [Item]) async throws -> [Result] {
    var results: [Result] = []
    for item in items {
        try Task.checkCancellation()
        results.append(await process(item))
    }
    return results
}
用于 UI 代码的 MainActor
// Apply at type level for consistent isolation
@MainActor
class ContentViewModel: ObservableObject {
    @Published var images: [UIImage] = []

    func fetchData() async throws {
        self.images = try await fetchImages()
    }
}

// Avoid MainActor.run when direct await works
await doMainActorStuff()  // Good
await MainActor.run { doMainActorStuff() }  // Unnecessary
Actor 隔离
actor DataCache {
    private var cache: [String: Data] = [:]

    func store(_ data: Data, forKey key: String) {
        cache[key] = data  // No await needed inside actor
    }

    nonisolated func cacheType() -> String {
        return "DataCache"  // No await needed - doesn't access isolated state
    }
}
应避免的常见问题
  1. 不要不必要地将函数标记为 async——异步调用约定会带来开销
  2. 切勿在 async/await 中使用 DispatchSemaphore——有死锁风险
  3. 不要创建无状态的 actors——应改用非隔离的异步函数
  4. 避免拆分隔离——不要在同一类型中混合不同的隔离域
  5. 检查任务取消状态——长时间运行的操作必须检查 Task.checkCancellation()
  6. 不要认为 async 意味着后台运行——如有需要,应显式将工作移至后台
  7. 避免过度切换上下文——在同一隔离域内组合操作
API 设计快速参考
命名约定
  • 类型/协议:UpperCamelCase
  • 其他所有内容:lowerCamelCase
  • 描述能力的协议:使用 -able、-ible、-ing 后缀(Equatable、ProgressReporting)
  • 工厂方法:以 make 开头(x.makeIterator())
  • 成对变更方法:祈使形式与过去分词形式(x.sort() / x.sorted())
按副作用命名方法
  • 无副作用:使用名词短语(x.distance(to: y))
  • 有副作用:使用祈使动词(x.append(y)、x.sort())
参数标签
  • 参数无法区分时省略标签:min(number1, number2)
  • 保留值的转换省略第一个标签:Int64(someUInt32)
  • 介词短语的标签放在介词处:x.removeBoxes(havingLength: 12)
  • 其他参数均添加标签
Swift 6 重大变更
必须显式使用 @MainActor 标记类型(SE-0401)

属性包装器不再自动推断 Actor 隔离。

@MainActor
struct LogInView: View {
    @StateObject private var model = ViewModel()
}
全局变量必须满足并发安全要求(SE-0412)
static let config = Config()  // Constant - OK
@MainActor static var state = State()  // Actor-isolated - OK
nonisolated(unsafe) var cache = [String: Data]()  // Unsafe - use with caution
其他变更
  • @UIApplicationMain/@NSApplicationMain 已弃用(请使用 @main)
  • 存在类型必须使用 any
  • 导入可见性需要显式访问控制
API 可用性模式
// Basic availability
@available(macOS 15, iOS 18, *)
func modernAPI() { }

// Deprecation with message
@available(*, deprecated, message: "Use newMethod() instead")
func oldMethod() { }

// Renaming with auto-fix
@available(*, unavailable, renamed: "newMethod")
func oldMethod() { }

// Runtime checking
if #available(iOS 18, *) {
    // iOS 18+ code
}

// Inverted checking (Swift 5.6+)
if #unavailable(iOS 18, *) {
    // iOS 17 and lower
}

主要区别:

  • deprecated - 发出警告,但允许使用
  • obsoleted - 从指定版本起报错
  • unavailable - 报错,并完全禁止使用

如何使用此技能

编写代码时
  1. 按照基于角色、优先保证清晰的原则应用命名约定
  2. 使用适当的隔离方式(UI 使用 @MainActor,可变状态使用 actor)
  3. 正确实现 async/await 模式,并妥善处理取消
  4. 遵循 Swift 6 并发模型——相信编译器的流程分析
  5. 为公共 API 编写清晰、简洁的摘要文档
审查代码时
  1. 检查是否违反并发安全规则
  2. 验证 actor 隔离和 Sendable 一致性是否正确
  3. 确保异步函数妥善处理取消
  4. 验证 API 命名是否遵循 Swift 指南
  5. 确认可用性标注对目标平台是否正确
代码质量标准
  • 尽量减少注释——尽可能让代码本身清晰易懂
  • 避免过度设计和不必要的抽象
  • 根据变量的角色而非类型使用有意义的名称
  • 遵循既定的项目架构和模式
  • 优先使用 count(where:),而不是 filter().count
  • 对固定大小且对性能要求高的数据使用 InlineArray
  • 相信编译器的并发流程分析——避免不必要的 Sendable 一致性声明

资源

references/

需要深入了解时加载的详细参考资料:

  • api-design.md - 完整的 API 设计约定、文档标准、参数指南和命名模式
  • concurrency.md - 详细的 async/await 模式、actor 最佳实践、常见陷阱、性能注意事项和线程安全模式
  • swift6-features.md - Swift 6/6.2 中的新语言特性、破坏性变更、迁移策略和现代模式
  • availability-patterns.md - @available 属性的全面用法、弃用策略和平台版本管理

当需要了解上述核心指南以外的详细信息时,请加载这些参考资料。

平台要求

  • 使用 Swift 6 特性需要 Swift 6.0+ 编译器
  • 使用 InlineArray 和增强的并发特性需要 Swift 6.2+
  • macOS 15.7+ 及适当的 SDK
  • 使用最新平台特性需要 iOS 18+
  • 使用 #available 检测运行时平台
  • 使用 @available 标注 API 的可用性

评论

支持 Markdown