Swift Strict Standard 是一套从 3 个生产 SwiftUI iOS 应用中提取的 Swift/SwiftUI 严格规范,适用场景为在 iOS/macOS 项目中编写、评审或重构 Swift 代码。以下按主题分段整理其规则内容。
【强制解包规则(CRITICAL)】 SW-01:生产代码中永不强制解包。资料给出反例(如 user!.name、URL(string:)!、calendar.date(byAdding:)!)与正例(使用 guard let / guard else 抛错)。极少例外需有理由:仅用于编程式视图的 required init?(coder:) 中的 fatalError(),以及 @IBOutlet 连接(但更推荐编程式 UI)。 SW-02:提前返回使用 guard let,作用域内绑定使用 if let;默认选 guard,仅当一个分支需要该值时才用 if-let。 SW-03:避免对关键操作使用 try? —— 它会静默吞掉错误。正例为用 do/catch 处理或向上传播;对真正可选的操作(如清理临时文件)可接受 try?。
【错误处理(CRITICAL)】 SW-04:使用遵循 LocalizedError 的自定义错误枚举(如 AppError,包含 invalidFolderName、containerUnavailable、networkUnavailable、unauthorized、serverError(Int) 等 case,并实现 errorDescription)。 SW-05:异步回调使用 Result 类型(如 Result<ASAuthorization, Error>,switch 处理 .success 与 .failure)。
【状态管理(HIGH)】 SW-06:使用 @Observable(iOS 17+),而非 ObservableObject。给出旧模式(ObservableObject + @Published,视图需 @StateObject)与新模式(@Observable final class,视图用 @State)对比;非响应式内部成员用 @ObservationIgnored。 SW-07:视图本地状态用 @State,注入用 @Environment(如 @Environment(.dismiss));面向 iOS 17+ 的新代码不要使用 @StateObject。 SW-08:单例必须为 @Observable,属性使用 private(set)(外部只读),构造函数为 private(如 SavedStore.shared)。
【并发安全(HIGH)】 SW-09:ViewModel 与更新 UI 的服务标注 @MainActor(已处于 MainActor 时无需 dispatch)。 SW-10:线程安全服务使用 actor(如 APIClient)。 SW-11:不要冗余使用 MainActor.run(函数已是 @MainActor 时直接赋值)。 SW-12:Task 取消配合 [weak self]:创建新任务前取消旧任务,sleep/await 后检查 Task.isCancelled,使用 [weak self] 防止循环引用。
【访问控制(HIGH)】 SW-13:默认 private,按需放开。private 用于实现细节(辅助方法、任务、缓存);private(set) 用于视图只读的状态;internal(默认)用于模块内访问;public 仅用于框架/库 API。 SW-14:类默认加 final,仅在有意子类化时省略。
【内存管理(MEDIUM)】 SW-15:所有异步闭包使用 [weak self](如 NotificationCenter 观察者闭包)。 SW-16:视图生命周期异步工作使用 .task { }(消失时自动取消),避免在 onAppear 中手动管理 Task。
【命名与风格(MEDIUM)】 SW-17:布尔属性使用 is、has、can、should 前缀(isLoading、isDirty、isSynced、hasCompletedOnboarding、canEdit)。 SW-18:动作使用方法(动词,如 save()、loadItems()),属性使用名词(如 folders、selectedFolder、errorMessage)。 SW-19:使用 .task { } 修饰符,而非 onAppear + Task。
【安全与漏洞规则】 SW-20:永不在 UserDefaults 中存储密钥(应使用 Keychain);非敏感偏好可接受(如 @AppStorage 存储 hasCompletedOnboarding)。 SW-21:加载前验证 URL(检查 scheme 为 https,否则抛错)。 SW-22:使用 App Transport Security,不添加例外;除非连接本地开发服务器,否则不要在 Info.plist 中添加 NSAllowsArbitraryLoads。
【Swift 6 并发(HIGH)】 SW-23:共享类型需 Sendable 一致性。值类型自动派生;引用类型需声明并强制不可变;需要可变时使用 actor(如 TokenStore);@unchecked Sendable 仅在书面说明理由时使用(如内部锁)。 SW-24:返回位置用 some P(不装箱、泛型特化),存储用 any P(异构存储需要);默认 some,仅当运行时具体类型可变时用 any。 SW-25:App Store 提交需隐私清单 PrivacyInfo.xcprivacy,列出跟踪域、required reason API 和收集数据类型;Apple 会拒绝缺少 required-reason API 声明(UserDefaults、FileTimestamp、SystemBootTime、DiskSpace)的提交。 SW-26:领域错误使用类型化 throws(Swift 6+)。反例为无类型 throws,正例为 throws(ConfigError) 并在 catch 中穷举 case,无需 fallback。建议在库边界与解析器使用类型化 throws,顶层 UI 处理保持无类型。 SW-27:以严格并发 complete 和 warnings as errors 编译。Package.swift 中设置 .swiftLanguageMode(.v6)、.enableUpcomingFeature("StrictConcurrency")、.unsafeFlags(["-warnings-as-errors"], .when(configuration: .release))。Swift 6 语言模式 + StrictConcurrency 在编译期捕获数据竞争,新代码从此开始。 SW-28:使用 Swift 6.2 特性实现固定大小与易用并发。Swift 6.2(2025 年发布)为当前稳定版,可采纳要点包括:InlineArray<N, T>(栈分配固定大小数组,无堆分配,编译期边界,适用于小型固定缓冲区);Approachable concurrency 默认值(按目标设置,默认在调用 actor 上运行 nonisolated 同步代码,减少附带 await 同时不牺牲数据竞争安全);WebAssembly 目标(Swift 编译为 WASM,用于浏览器与边缘场景);C++ 互操作(比 6.0 更深,可用于对接现有 C++ 库);Containerization(Apple 官方项目,用 Swift 编写,在 Apple silicon 上原生运行 Linux 容器,适用于无 Docker Desktop 的构建/测试流水线)。
【漏洞检查清单】 生产代码无强制解包(!);关键操作(文件创建、认证、数据保存)无 try?;UserDefaults 无密钥(用 Keychain);异步闭包无强 self 捕获;所有 ViewModel 使用 @Observable + final;UI 更新代码为 @MainActor 或在 MainActor.run 上;所有 .task { } 工作检查取消;访问控制默认 private;Info.plist 无 NSAllowsArbitraryLoads。