移动/游戏
写现代 Swift 核心代码时应用语言新特性(if/swit…
在编写非并发、非 SwiftUI 的 Swift 核心代码(泛型、协议、枚举、闭包)时,用现代语言特性替换旧写法,同时保持行为与求值顺序不变。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
写现代 Swift 核心代码时应用语言新通用
解决思路
- 现代化改造流程:先固定当前行为与求值顺序,做一次语义等价重写,编译受影响模块,运行针对性 fixture/测试;若行为改变先修复再继续,重复直到行为保持一致。
- 用 if/switch 表达式直接赋值、返回或初始化:如 `let icon = if isComplete { "checkmark.circle.fill" } else { "circle" }`,`let label = switch status { case .draft: "Draft" ... }`,也可直接用于 return 位置。
- if/switch 表达式规则:每个分支必须产生同类型值;分支只能是单个表达式,不允许多语句;作为函数参数时用括号包裹以避免歧义。
- 用 typed throws(Swift 6+)声明函数抛出的具体错误类型:`func validate(username: String) throws(ValidationError) -> String`,调用方 catch 到的 error 即为该类型,可做穷尽 switch 而无需强转。
- typed throws 规则:仅当调用方能从穷尽错误处理中获益时使用 `throws(SomeError)`;错误来源混合时用无类型 `throws`;改造只有一个本地错误枚举的 helper 时优先 `throws(ErrorEnum)` 并注明 Swift 6+;`throws(Never)` 表示语法上抛错但实际永不抛出,适用于泛型场景;typed throws 会传播,调用 `throws(A)` 与 `throws(B)` 的函数必须抛出覆盖两者的类型或改用无类型 throws。
- 用 `@resultBuilder` 构建 DSL 语法:实现 `buildBlock`(组合语句)、`buildExpression`(单值)、`buildOptional`(无 else 的 if)、`buildEither`(if/else)、`buildArray`(for..in)、`buildFinalResult`(可选后处理),例如自定义 `ArrayBuilder<Element>` 并配合 `func makeItems(@ArrayBuilder<String> content: () -> [String]) -> [String]`。
- 用自定义 `@propertyWrapper` 封装存储与访问模式:`wrappedValue` 是主 getter/setter,`projectedValue`(通过 `$property` 访问)提供元数据或绑定,例如 `@Clamped(0...100) var level: Int = 50` 在 setter 中做 min/max 钳制。
- property wrapper 设计规则:可组合(`@A @B var x` 先应用外层);当简单计算属性已足够时不要使用 property wrapper。
- 区分 `some Protocol`(不透明类型)与 `any Protocol`(存在类型):`-> some P` 的所有返回分支必须是同一个固定具体类型,编译器知道具体类型;`any P` 是运行时可持有任意遵循类型的盒子,使用动态派发且可能堆分配。
- some/any 选择规则:默认用 `some`(隐藏实现、保留类型身份、静态派发性能更好、参数位置可替代简单泛型);仅当需要异构集合或运行时类型灵活性、或需要擦除带 `Self`/关联类型要求的协议时才用 `any`。
- 用 `guard` 强制前置条件并提前退出,保持 happy path 左对齐、减少嵌套:解包可选 `guard let order else { throw OrderError.missing }`、校验条件、布尔检查、模式匹配 `guard case .confirmed(let date) = order.status else { ... }`。
- guard 最佳实践:前置条件用 guard,分支逻辑用 if;合并相关 guard(`guard let a, let b else { return }`);else 块必须退出作用域(return/throw/continue/break/fatalError);使用简写解包 `guard let value else { ... }`(Swift 5.7+)。
- 用 `Never` 表示永不产生值的代码路径:如 `func crashWithDiagnostics(_ message: String) -> Never`、`Result<String, Never>`(永不失败的结果)、对 `Result<String, Never>` 做 switch 时无需 .failure 分支。
- Never 的准确表述:它是 uninhabited 类型,仅在值表达式可用或可推断的位置表现得像 bottom type;它不是通用类型见证,不会隐式遵循任意协议,也不能满足 `T: P` 这类泛型约束(除非该约束对 Never 本身有效)。
- 用 Swift 5.7+ Regex builder DSL 编写编译期检查、可读性强的正则:如 `Regex { Capture { /\d{4}/ }; "-"; Capture { /\d{2}/ }; "-"; Capture { /\d{2}/ } }`,配合 `firstMatch(of:)` 与 `match.output` 解构;用 `TryCapture { ... } transform: { ... }` 做带转换的捕获。
- Regex 选择:复杂模式、可复用组件、强类型捕获用 builder;简单模式或熟悉正则语法时用字面量 `/pattern/`;两者可混用(在 builder 块中嵌入 `/.../` 字面量)。
- Codable 基础整形:简单重命名用 `CodingKeys`,仅在真实 payload 形状或转换不匹配时写自定义解码;深入解码实现与验证交给 `swift-codable`。
- 优先使用现代集合 API 而非手写循环:`count(where:)` 替代 `.filter { }.count`;`contains(where:)`(首个匹配即短路);`first(where:)`/`last(where:)`;`String.replacing()`(Swift 5.7+,返回新字符串,如 `rawText.replacing(/\s+/, with: " ")`);`compactMap` 解包转换结果;`flatMap` 展平嵌套集合;`Dictionary(grouping:by:)`;`reduce(into:)` 高效累积。
- 格式化显示用 `.formatted()` 与 `Text(_:format:)`;样式选择、解析、本地化测试与可复用 formatter 设计交给 `swift-formatstyle`。
- 字符串插值:扩展 `DefaultStringInterpolation` 实现领域特定格式化;多行字符串用 `"""`(缩进相对闭合的 `"""`)。
- 避免常见错误:能用 `some` 时不要用 `any`(且每个 `-> some P` 分支必须返回同一具体类型);不要手写循环或 `.filter { }.count`;不要用 `DateFormatter` 而用 FormatStyle;不要强解包 Codable 解码(可选/缺失键用 `decodeIfPresent` 加默认值);现代化时不要重排前置条件(用 guard 且不要把规范化/转换移到校验之前);修正 `@c` 签名时说明 `UnsafeBufferPointer` 是 Swift struct/value wrapper 并点名拒绝 `String`、`Array`、闭包与泛型占位符;单一明确错误类型时不要忽略 typed throws;不要过度使用 property wrapper(无复用或 projected value 需求时计算属性更简单);描述 `Never` 时不要遗漏其不隐式遵循任意协议、不满足任意 `T: P` 约束的说明;不要越界实现兄弟技能的内容(点名归属技能后停止,不要为 CodingKeys、decoder、formatter、SwiftUI 或并发写片段)。
- 按 review checklist 自检:`some` 仅用于所有不透明返回分支同一具体类型;前置条件用 guard、计数用 `count(where:)`;用 `.formatted()` 而非 `DateFormatter`/`NumberFormatter`;Codable 用 `CodingKeys` 做 API 映射、可选字段用 `decodeIfPresent` 加默认值;条件赋值用 if/switch 表达式、property wrapper 有明确复用理由;复杂模式用 Regex builder;单一本地错误域用 typed throws 并注明 Swift 6+ 兼容;`@c` 修正中称 `UnsafeBufferPointer` 为 Swift struct/value wrapper 并逐一点名被拒绝的 Swift-only 类型;`Never` 说明使用 uninhabited 与 bottom-like 并声明无隐式任意协议/泛型遵循;深入 Codable 路由到 `swift-codable`、FormatStyle API 路由到 `swift-formatstyle`、市场/本地化显示 QA 路由到 `ios-localization`、命名/并发/SwiftUI 路由到对应兄弟技能。
适用边界 · 注意事项
- 涉及并发(concurrency)的代码——交给 `swift-concurrency`。
- 涉及 SwiftUI 状态与视图的代码——交给 `swiftui-patterns`。
- 需要深入 Codable 实现与验证、详细格式化/本地化、或 API 命名规范时——分别交给 `swift-codable`、`swift-formatstyle`、`swift-api-design-guidelines`。