| name | ios-issue-fix |
| description | Guides iOS issue diagnosis and fix through a five-phase methodology from understanding the issue to verified fix. Use when fixing bugs, crashes, UI anomalies, performance issues, or any unexpected behavior in iOS applications. |
iOS Issue 修复
核心原则
先读懂问题,再理解上下文,后动代码,改完必审查。
大多数 Bug 不是崩溃,而是"功能没按预期工作"。修复的关键是理解预期行为与实际行为的差异,以及这个差异在代码中是如何产生的。
修复前必须回答的 4 个问题
- 预期行为是什么? — 产品/设计/用户期望看到什么结果
- 实际行为是什么? — 现在实际发生了什么
- 差异在哪里产生? — 代码中哪个环节导致了偏差
- 改动会不会波及其他地方? — 这段代码还被谁依赖
绝对禁止
- Issue 描述没读完就开始改代码
- 不理解原有代码的意图就直接修改
- 不检查修复对其他模块的影响就提交 PR
- 用
try! / ! / asyncAfter / 空 catch {} 掩盖问题
复杂度速判
在进入五阶段流程前,先快速评估问题复杂度,决定走完整流程还是精简流程:
| 级别 | 判断标准 | 流程路径 | 典型场景 |
|---|
| S — 简单 | 根因明显、影响范围单一、改动 < 10 行 | 阶段一 → 阶段四 → 阶段五 | 拼写错误、硬编码值修正、简单的 UI 微调 |
| M — 中等 | 需要排查定位、涉及 2-3 个文件、有上下游依赖 | 完整五阶段流程 | 状态管理 Bug、数据展示异常、导航流程错误 |
| L — 复杂 | 涉及多模块/跨层/并发/架构层问题、复现困难 | 完整五阶段流程 + 额外评审 | 偶现崩溃、性能退化、多线程数据竞争 |
特别规则: 崩溃类问题一律按 M 级及以上 处理,即使看起来简单。崩溃的影响范围往往比表面更广。
五阶段流程
阶段一:阅读与理解问题
从 Issue 描述中提取"预期 vs 实际"差异。对问题进行 7 大类分类,明确复现条件,输出"问题理解卡片"。如果无法写出清晰的卡片,说明 Issue 还没读懂,不要开始下一步。
详细模板与追问清单 → references/issue-classification.md
门控输出: 完成「问题理解卡片」,包含预期/实际行为、分类、复现路径。无法写出清晰卡片则不进入下一阶段。
阶段二:项目上下文关联分析
定位问题涉及的代码范围,理解原有代码的设计意图。按问题类型选择不同定位策略,用 5 步检查法理解代码意图,通过 Git 历史追溯变更原因,输出"影响范围图"。
定位策略、5 步检查法、Git 命令与影响范围图 → references/root-cause-analysis.md
门控输出: 完成「影响范围图」,包含问题文件/函数、上下游依赖、关联组件。影响范围不清楚则不进入下一阶段。
阶段三:根因定位
找到导致差异的精确代码位置和原因。按问题类型选择对应排查策略,SwiftUI 问题参考专项指南,最终用一句话描述根因:"因为 X,导致 Y,所以用户看到了 Z"。
分类型排查策略 → references/debug-by-type.md
SwiftUI 专项排查 → references/swiftui-debugging.md
Xcode 调试工具速查 → references/xcode-tools.md
门控输出: 完成「根因一句话描述」。说不出"因为 X → 导致 Y → 用户看到 Z"则说明根因未定位,不进入修复阶段。
阶段四:实现修复
针对根因实现最小、安全、可测试的修复。遵循最小修改原则、在根因处修复、保持原有代码风格、使用 Swift 安全修复模式。为 Bug 编写"先红后绿"的测试。
修复原则、安全模式与测试选型 → references/fix-patterns.md
门控输出: 修复代码已实现 + Bug 场景测试已通过(先红后绿)。测试未通过则不进入审查阶段。
阶段五:修复审查与影响评估
确保修复有效且不引入新问题。完成代码自审清单,进行 5 层影响范围验证,按多维度(设备/系统/模式/网络/构建)验证,按规范提交 PR。
自审清单、5 层验证与 PR 模板 → references/verification.md
门控输出: 自审清单全部通过 + 影响范围验证完成 + PR 已按规范提交。
Topic Router — 问题类型导航
| 问题类型 | 主要参考文件 | 辅助参考 |
|---|
| UI 显示异常 | debug-by-type.md → UI 显示异常 | xcode-tools.md(View Debugger) |
| SwiftUI 视图不更新 | swiftui-debugging.md → 视图不更新 | debug-by-type.md → 数据不更新 |
| SwiftUI 性能问题 | swiftui-debugging.md → 性能问题 | xcode-tools.md(Instruments) |
| SwiftUI 导航问题 | swiftui-debugging.md → 导航问题 | debug-by-type.md → 交互异常 |
| 功能逻辑错误 | debug-by-type.md → 功能逻辑错误 | root-cause-analysis.md |
| 数据问题 | debug-by-type.md → 数据问题 | xcode-tools.md(抓包/LLDB) |
| 交互异常 | debug-by-type.md → 交互不符合预期 | swiftui-debugging.md → 动画问题 |
| 兼容性问题 | debug-by-type.md → 兼容性问题 | verification.md → 多维度验证 |
| 崩溃 | debug-by-type.md → 崩溃 | xcode-tools.md(Zombie/ASan) |
| 线上崩溃 / 崩溃符号化 / 崩溃日志解读 | crash-analysis.md | debug-by-type.md → 崩溃 |
| 网络请求失败 / HTTP 错误 / Codable 解析 / SSL | network-debugging.md | debug-by-type.md → 数据问题 |
| 性能问题 | xcode-tools.md(Time Profiler) | swiftui-debugging.md → 性能 |
输出格式规范
修复流程中需产出以下三个关键输出:
问题理解卡片(阶段一输出)
问题:[用自己的话复述问题,不超过两句]
预期:[应该怎样] 实际:[现在怎样]
分类:[7 类之一] 严重程度:[P0-P3]
复现路径:[步骤 1 → 步骤 2 → 出现问题]
影响范围图(阶段二输出)
文件:[路径:行号] 函数:[函数名]
上游:[调用方列表] 下游:[依赖列表]
关联组件:[可能波及的组件 + 原因]
根因一句话描述(阶段三输出)
因为 [X 根因],导致 [Y 直接后果],所以用户看到了 [Z 现象]
深层问题警告信号
以下情况说明不是简单 Bug,需要暂停讨论:
| 信号 | 含义 | 应对 |
|---|
| 修复 A 页面导致 B 页面出问题 | 状态管理存在全局耦合 | 讨论状态管理方案重构 |
| 同一 Bug 在多个页面重复出现 | 公共组件或基础逻辑有缺陷 | 修复公共层而非逐页面打补丁 |
| 修复需要在 10+ 处添加相同 guard let | 数据流设计有缺陷 | 重新设计数据流 |
| 每次修 Bug 都暴露新的隐藏 Bug | 技术债积累过多 | 安排技术债清理 |
| 连续三次修复尝试均失败 | 对问题理解可能是错的 | 回到阶段一重新理解问题 |
此时应立即停止打补丁,记录所有关联问题,评估是否需要架构优化,与团队讨论修复策略。如需重构,单独排期,不在 Bug 修复 PR 中混入。
何时停止修复尝试
以下任一条件满足时,应停止当前修复尝试并升级处理:
| 退出条件 | 触发标准 | 下一步行动 |
|---|
| 修复尝试次数超限 | 连续 3 次修复尝试均未解决问题 | 回到阶段一重新理解问题,考虑是否误判了根因 |
| 影响范围不可控 | 修复导致 2 个以上新问题出现 | 回退修改,重新评估影响范围,必要时拉其他开发者评审 |
| 超出能力边界 | 涉及不熟悉的底层框架/第三方 SDK 内部问题 | 记录已知信息,升级给领域专家或联系 SDK 提供方 |
| 问题无法复现 | 投入 > 2 小时仍无法稳定复现 | 添加详细日志埋点,等待下次复现时收集信息 |
| 需要架构变更 | 修复方案需要改动 5+ 个文件或跨 3+ 个模块 | 转为技术方案评审,单独排期,不在 Bug 修复中混入 |
| 时间投入过高 | 排查时间超过预期的 3 倍仍无进展 | 暂停并记录当前进展,寻求团队协助或换人排查 |
红旗信号表
| 违规行为 | 为什么是错误的 | 正确做法 |
|---|
| Issue 没读完就改代码 | 理解偏差导致修错方向 | 完成问题理解卡片 |
| 不看原有代码直接改 | 破坏原有设计意图 | 完成上下文分析 |
| 在 UI 层修数据层的问题 | 根因未修复,其他页面仍有问题 | 追溯到根因所在层修复 |
| 修完不验证波及面 | 修一个 Bug 引入两个新 Bug | 完成影响范围验证 |
用 asyncAfter 修时序问题 | 不同设备速度不同,治标不治本 | 找到正确的生命周期事件点 |
用 try! / ! 消除警告 | 运行期崩溃比编译期警告更危险 | 用 guard let / if let / ?? |
空 catch {} 吞异常 | 丢失错误信息,排查无据可依 | catch 中至少记录日志 |
| "模拟器上好了"就结束 | 真机行为可能完全不同 | 真机验证为最终标准 |
| 改了公共组件不验其他调用方 | 影响面可能远超预期 | 全局搜索所有调用方逐一验证 |
| 没写测试就提 PR | 无法防止未来回归 | 先红后绿,覆盖 Bug 场景 |
修复完成清单
| 维度 | 检查项 |
|---|
| 问题 | 能用一句话解释根因 / 复现路径验证通过 / 预期行为验证通过 |
| 代码 | 修复针对根因 / 范围最小化 / 无强制解包和空 catch / 遵循项目风格 |
| 测试 | 已编写覆盖 Bug 场景的测试 / 完整测试套件通过 / 真机验证通过 |
| 影响 | 同页面验证 / 上下游页面验证 / 公共代码调用方验证 / Dark Mode+多屏验证 |
与其他 Skill 的协作
- ios-feature-impl:修复过程中发现需求理解偏差时,回到需求阅读流程
- code-review:修复 PR 的审查流程