SKILL.md
readonlyread-only
name
swiftui-expert-skill
description
用於撰寫、審查或重構 iOS 或 macOS 的 SwiftUI 程式碼,包含狀態管理與 `@Observable` 資料流、檢視組合與失效/效能、列表與 `ForEach` 識別、環境使用、本地化、動畫、Liquid Glass 採用、遷移軟棄用 API,或使用 Instruments `.trace` 擷取/分析卡頓、掉幀、CPU 熱點或過多檢視更新。
SwiftUI Expert Skill
操作規則
- 每次任務開始時先查閱
references/latest-apis.md,避免使用已棄用的 API - 除非必要,否則優先使用原生 SwiftUI API 而非 UIKit/AppKit 橋接
- 專注於正確性與效能;不強制特定架構(MVVM、VIPER 等)
- 鼓勵將商業邏輯與檢視分離以提升可測試性,但不強制特定做法
- 遵循 Apple 的 Human Interface Guidelines 與 API 設計模式
- 僅在使用者明確要求時才採用 Liquid Glass(參見
references/liquid-glass.md) - 將效能最佳化視為建議而非必要條件
- 對版本特定 API 使用
#available搭配合理的降級方案
任務流程
審查現有 SwiftUI 程式碼
- 閱讀待審查的程式碼,判斷哪些主題適用
- 標記已棄用的 API(對照
references/latest-apis.md) - 針對每個相關主題執行下方的主題路由器
- 驗證 iOS 26+ 功能的
#available防護與降級路徑
改善現有 SwiftUI 程式碼
- 根據主題路由器的主題審查目前實作
- 將棄用 API 替換為
references/latest-apis.md中的現代等效 API - 重構熱點路徑以減少不必要的狀態更新
- 將複雜的檢視主體拆分為獨立的子檢視
- 遇到
UIImage(data:)時建議圖片降採樣(選擇性最佳化,參見references/image-optimization.md)
實作新的 SwiftUI 功能
- 先設計資料流:區分擁有狀態與注入狀態
- 為最佳差異化建構檢視(及早提取子檢視)
- 套用正確的動畫模式(隱式 vs 顯式、轉場)
- 所有可點擊元素使用
Button;加入無障礙分組與標籤 - 使用
#available防護版本特定 API 並提供降級方案
錄製新的 Instruments trace
當使用者要求「錄製 trace」、「分析 App」、「擷取 session」等時觸發。完整參考:references/trace-recording.md。
- 確認目標 — 附加到執行中的 App、啟動 App、或錄製所有程序?若使用者未說明,請詢問。必要時列出已連接裝置:
python3 "${SKILL_DIR}/scripts/record_trace.py" --list-devices - 根據目標類型選擇模板 —
SwiftUI模板會在真實裝置(實體 iOS/iPadOS 裝置或主機 Mac)上填入 SwiftUI 跑道。唯一的例外是 iOS 模擬器,SwiftUI 跑道會是空的 — 此時改用--template "Time Profiler"(仍提供 Time Profiler + Hangs + Animation Hitches)。務必檢查--list-devices:simulators類型 →Time Profiler;devices類型(真實裝置與主機 Mac)→ 預設SwiftUI。完整決策表在references/trace-recording.md。 - 開始錄製。對於代理驅動的 session(使用者說「我完成時告訴你」),在背景啟動並使用停止檔案:
對於互動式 session,直接告知使用者完成時按 Ctrl+C。python3 "${SKILL_DIR}/scripts/record_trace.py" \ --device "<name|udid>" --attach "<AppName>" \ --stop-file /tmp/stop-trace --output ~/Desktop/session.trace - 發出停止訊號 — 當使用者表示已操作完 App 時,執行
touch /tmp/stop-trace。腳本會乾淨地對 xctrace 發送 SIGINT 並等待最多 60 秒完成。 - 分析 產生的 trace(進入下方的「Trace 驅動改善」流程)。
Trace 驅動改善(提供 Instruments .trace)
每當使用者的請求提及 .trace 檔案時觸發。目標 SwiftUI 原始檔是選擇性的 — 若有提供,引用特定行數;若無,根據 trace 已揭露的檢視名稱與符號建議應查看的位置。
完整參考:references/trace-analysis.md。組合模式摘要:
- 界定分析範圍。 問自己:使用者想要整個 trace,還是某個片段?
- 「聚焦在 X / 在 X 之後 / 在 X 與 Y 之間 / 在 X 期間」 → 先解析出時間區間(見步驟 2)。
- 無範圍提示 → 分析整個 trace。
- 解析時間區間(僅在使用者指定範圍時)。 解析器提供兩種探索模式:
兩種模式都接受# 尋找標記感興趣區域開始/結束的日誌: python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <path> \ --list-logs --log-message-contains "loaded feed" --log-limit 5 # 或列出 os_signpost 區間(成對的 begin/end),可按名稱篩選: python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <path> \ --list-signposts --signpost-name-contains "ImageDecode"--window START_MS:END_MS來限定探索範圍。選取符合使用者描述的time_ms(日誌)或start_ms/end_ms(signpost)。建構類似--window 10400:11700的區間。 - 執行主要分析(可加或不加
--window):python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <path> \ --json-only --top 10 [--window START_MS:END_MS] - 搭配
references/trace-analysis.md解讀 — 關鍵診斷:- 每個關聯中的
main_running_coverage_pct(<25% = 被阻塞;≥75% = CPU 密集)。 swiftui-causes.top_sources揭示更新持續發生的原因 — 高邊緣計數的來源如UserDefaultObserver.send()或寬廣的EnvironmentWriter條目屬於結構性失效錯誤。修正一個通常能消除許多下游熱點檢視。
- 每個關聯中的
- 當特定檢視顯示為昂貴時,詢問是誰在使其失效。 使用
--fanin-for "<view name>"取得驅動更新的來源節點排名列表。 - 選擇性對應到原始碼。 若使用者指定了檔案,讀取該檔案並將檢視名稱/使用者程式碼符號與其中的識別符匹配。若無,根據 SwiftUI 回報的檢視名稱建議應開啟哪些檔案。
- 回傳優先順序計畫。 引用證據(覆蓋率百分比、熱點符號、重疊檢視、日誌時間戳、原因圖邊緣),並將每個建議導向主題路由器參考。
- 僅在使用者要求編輯時才編輯程式碼。
主題路由器
針對目前任務相關的每個主題,查閱對應的參考檔案:
| 主題 | 參考 |
|---|---|
| 狀態管理 | references/state-management.md |
| 檢視組合 | references/view-structure.md |
| 效能 | references/performance-patterns.md |
| 列表與 ForEach | references/list-patterns.md |
| 佈局 | references/layout-best-practices.md |
| Sheet 與導航 | references/sheet-navigation-patterns.md |
| ScrollView | references/scroll-patterns.md |
| 焦點管理 | references/focus-patterns.md |
| 動畫(基礎) | references/animation-basics.md |
| 動畫(轉場) | references/animation-transitions.md |
| 動畫(進階) | references/animation-advanced.md |
| 無障礙 | references/accessibility-patterns.md |
| Swift Charts | references/charts.md |
| Charts 無障礙 | references/charts-accessibility.md |
| 圖片最佳化 | references/image-optimization.md |
| Liquid Glass(iOS 26+) | references/liquid-glass.md |
| macOS 場景 | references/macos-scenes.md |
| macOS 視窗樣式 | references/macos-window-styling.md |
| macOS 檢視 | references/macos-views.md |
| 文字模式 | references/text-patterns.md |
| 本地化 | references/localization.md |
| 棄用 API 查詢 | references/latest-apis.md |
| 處理軟棄用 API | references/soft-deprecation.md |
| 預覽 | references/previews.md |
| Instruments trace 分析 | references/trace-analysis.md |
| Instruments trace 錄製 | references/trace-recording.md |
正確性檢查清單
以下是硬性規則 — 違反即為錯誤:
- [ ]
@State屬性為private - [ ]
@Binding僅用於子檢視修改父檢視狀態 - [ ] 傳入的值絕不宣告為
@State或@StateObject(它們會忽略更新) - [ ]
@StateObject用於檢視擁有的物件;@ObservedObject用於注入的物件 - [ ] iOS 17+:
@State搭配@Observable;@Bindable用於需要綁定的注入可觀察物件 - [ ]
ForEach使用穩定的識別(絕不使用.indices/\.offset;id 的生命週期超過檢視,且不從可變內容衍生) - [ ] 每個
ForEach元素的檢視數量固定;List行數為一元 - [ ] 自訂
@Environment/@FocusedValue鍵中不儲存閉包 - [ ] 自訂
@Entry預設值為穩定的(無Model()/Date()/UUID()表達式) - [ ]
.animation(_:value:)總是包含value參數 - [ ]
@FocusState屬性為private - [ ] 在
.focusable()檢視的點擊手勢處理器中無多餘的@FocusState寫入 - [ ] iOS 26+ API 使用
#available防護並提供降級方案 - [ ] 使用圖表類型的檔案中包含
import Charts - [ ] 預覽使用自包含的模擬資料;不依賴即時服務或網路
參考資料
references/latest-apis.md— 每次任務先讀取。 從棄用到現代的 API 轉換(iOS 15+ 到 iOS 26+)references/state-management.md— 屬性包裝器、資料流、@Observable遷移references/view-structure.md— 檢視提取、容器模式、@ViewBuilderreferences/performance-patterns.md— 熱點路徑最佳化、更新控制、_logChanges()references/list-patterns.md— ForEach 識別、Table(iOS 16+)、內聯篩選陷阱references/layout-best-practices.md— 佈局模式、GeometryReader 替代方案references/accessibility-patterns.md— VoiceOver、Dynamic Type、分組、特性references/animation-basics.md— 隱式/顯式動畫、時序、效能references/animation-transitions.md— 檢視轉場、matchedGeometryEffect、Animatablereferences/animation-advanced.md— 階段/關鍵幀動畫(iOS 17+)、@Animatable巨集(iOS 26+)references/charts.md— Swift Charts 標記、軸、選取、樣式、Chart3D(iOS 26+)references/charts-accessibility.md— Charts VoiceOver、Audio Graph、降級策略references/sheet-navigation-patterns.md— Sheets、NavigationSplitView、Inspectorreferences/scroll-patterns.md— ScrollViewReader、程式化滾動references/focus-patterns.md— 焦點狀態、可聚焦檢視、聚焦值、預設焦點、常見陷阱references/image-optimization.md— AsyncImage、降採樣、快取references/liquid-glass.md— iOS 26+ Liquid Glass 效果與降級模式references/macos-scenes.md— Settings、MenuBarExtra、WindowGroup、多視窗references/macos-window-styling.md— 工具列樣式、視窗大小、Commandsreferences/macos-views.md— HSplitView、Table、PasteButton、AppKit 互通references/previews.md—#Preview巨集、@Previewable(iOS 18+)、預覽特性、自包含預覽的模擬資料模式references/text-patterns.md— Text 初始化器選擇、逐字 vs 本地化references/localization.md— String Catalogs、套件的#bundle、LocalizedStringResource、語言感知格式化、RTL 佈局、翻譯者註解references/soft-deprecation.md— 如何處理軟棄用 API(何時遷移、範圍規則、不相關編輯時不遷移)references/trace-analysis.md— 透過scripts/analyze_trace.py解析 Instruments.trace檔案;解讀主執行緒覆蓋率、高嚴重性 SwiftUI 更新、掉幀敘述,並將發現對應回原始檔references/trace-recording.md— 透過scripts/record_trace.py錄製新的 trace:附加到執行中的 App、全新啟動、或擷取手動停止的 session;支援代理驅動流程的停止檔案






