$npx -y skills add AvdLee/SwiftUI-Agent-Skill --skill swiftui-expert-skillUse when writing, reviewing, or refactoring SwiftUI code for iOS or macOS, including state management and @Observable data flow, view composition and invalidation/performance, lists and ForEach identity, environment usage, localization, animations, Liquid Glass adoption, migr
| 1 | # SwiftUI Expert Skill |
| 2 | |
| 3 | ## Operating Rules |
| 4 | |
| 5 | - Consult `references/latest-apis.md` at the start of every task to avoid deprecated APIs |
| 6 | - Prefer native SwiftUI APIs over UIKit/AppKit bridging unless bridging is necessary |
| 7 | - Focus on correctness and performance; do not enforce specific architectures (MVVM, VIPER, etc.) |
| 8 | - Encourage separating business logic from views for testability without mandating how |
| 9 | - Follow Apple's Human Interface Guidelines and API design patterns |
| 10 | - Only adopt Liquid Glass when explicitly requested by the user (see `references/liquid-glass.md`) |
| 11 | - Present performance optimizations as suggestions, not requirements |
| 12 | - Use `#available` gating with sensible fallbacks for version-specific APIs |
| 13 | |
| 14 | ## Task Workflow |
| 15 | |
| 16 | ### Review existing SwiftUI code |
| 17 | - Read the code under review and identify which topics apply |
| 18 | - Flag deprecated APIs (compare against `references/latest-apis.md`) |
| 19 | - Run the Topic Router below for each relevant topic |
| 20 | - Validate `#available` gating and fallback paths for iOS 26+ features |
| 21 | |
| 22 | ### Improve existing SwiftUI code |
| 23 | - Audit current implementation against the Topic Router topics |
| 24 | - Replace deprecated APIs with modern equivalents from `references/latest-apis.md` |
| 25 | - Refactor hot paths to reduce unnecessary state updates |
| 26 | - Extract complex view bodies into separate subviews |
| 27 | - Suggest image downsampling when `UIImage(data:)` is encountered (optional optimization, see `references/image-optimization.md`) |
| 28 | |
| 29 | ### Implement new SwiftUI feature |
| 30 | - Design data flow first: identify owned vs injected state |
| 31 | - Structure views for optimal diffing (extract subviews early) |
| 32 | - Apply correct animation patterns (implicit vs explicit, transitions) |
| 33 | - Use `Button` for all tappable elements; add accessibility grouping and labels |
| 34 | - Gate version-specific APIs with `#available` and provide fallbacks |
| 35 | |
| 36 | ### Record a new Instruments trace |
| 37 | Trigger when the user asks to "record a trace", "profile the app", "capture a session", etc. Full reference: `references/trace-recording.md`. |
| 38 | |
| 39 | 1. **Confirm target** — attach to a running app, launch an app, or record all processes? If the user didn't say, ask. List connected devices when useful: |
| 40 | ```bash |
| 41 | python3 "${SKILL_DIR}/scripts/record_trace.py" --list-devices |
| 42 | ``` |
| 43 | 2. **Pick a template based on target kind** — the `SwiftUI` template populates the SwiftUI lane on any **real device**: a physical iOS/iPadOS device **or the host Mac**. The only exception is the **iOS Simulator**, where the SwiftUI lane comes back empty — switch to `--template "Time Profiler"` in that case (still gives Time Profiler + Hangs + Animation Hitches). Always check `--list-devices`: `simulators` kind → `Time Profiler`; `devices` kind (real devices and the host Mac) → default `SwiftUI`. Full decision table in `references/trace-recording.md`. |
| 44 | 3. **Start the recording**. For agent-driven sessions where the user says "I'll tell you when I'm done", start in the background and use a stop-file: |
| 45 | ```bash |
| 46 | python3 "${SKILL_DIR}/scripts/record_trace.py" \ |
| 47 | --device "<name|udid>" --attach "<AppName>" \ |
| 48 | --stop-file /tmp/stop-trace --output ~/Desktop/session.trace |
| 49 | ``` |
| 50 | For interactive sessions, just tell the user to press Ctrl+C when done. |
| 51 | 4. **Signal stop** — when the user says they've finished exercising the app, `touch /tmp/stop-trace`. The script cleanly SIGINTs xctrace and waits up to 60s for finalisation. |
| 52 | 5. **Analyse** the resulting trace (flow into the "Trace-driven improvement" workflow below). |
| 53 | |
| 54 | ### Trace-driven improvement (Instruments `.trace` provided) |
| 55 | Trigger whenever the user's request references a `.trace` file. A target SwiftUI source file is **optional** — if given, cite specific lines; if not, recommend where to look based on view names and symbols the trace already reveals. |
| 56 | |
| 57 | Full reference: `references/trace-analysis.md`. Summary of the composition pattern: |
| 58 | |
| 59 | 1. **Scope the analysis.** Ask yourself: does the user want the whole trace, or a slice? |
| 60 | - "focus on X / after X / between X and Y / during X" → **resolve to a window first** (see step 2). |
| 61 | - No scoping cue → analyse the whole trace. |
| 62 | 2. **Resolve a window (only if the user scoped).** The parser exposes two discovery modes: |
| 63 | ```bash |
| 64 | # Find a log that marks the start/end of the region of interest: |
| 65 | python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <path> \ |
| 66 | --list-logs --log-message-contains "loaded feed" --log-limit 5 |
| 67 | # Or list os_signpost intervals (paired begin/end), filterable by name: |
| 68 | python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trac |