Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Reviews, improves, and writes SwiftUI code following state management, view composition, performance, and iOS 26+ Liquid Glass best practices.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
SKILL.md
1---2name: swiftui-expert-skill3description: Use when writing, reviewing, or refactoring SwiftUI code for iOS or macOS, including state management, view composition, performance, Liquid Glass adoption, or Instruments `.trace` capture/analysis for hangs, hitches, CPU hotspots, or4excessive view updates.5---67# SwiftUI Expert Skill89## Operating Rules1011- Consult `references/latest-apis.md` at the start of every task to avoid deprecated APIs12- Prefer native SwiftUI APIs over UIKit/AppKit bridging unless bridging is necessary13- Focus on correctness and performance; do not enforce specific architectures (MVVM, VIPER, etc.)14- Encourage separating business logic from views for testability without mandating how15- Follow Apple's Human Interface Guidelines and API design patterns16- Only adopt Liquid Glass when explicitly requested by the user (see `references/liquid-glass.md`)17- Present performance optimizations as suggestions, not requirements18- Use `#available` gating with sensible fallbacks for version-specific APIs1920## Task Workflow2122### Review existing SwiftUI code23- Read the code under review and identify which topics apply24- Flag deprecated APIs (compare against `references/latest-apis.md`)25- Run the Topic Router below for each relevant topic26- Validate `#available` gating and fallback paths for iOS 26+ features2728### Improve existing SwiftUI code29- Audit current implementation against the Topic Router topics30- Replace deprecated APIs with modern equivalents from `references/latest-apis.md`31- Refactor hot paths to reduce unnecessary state updates32- Extract complex view bodies into separate subviews33- Suggest image downsampling when `UIImage(data:)` is encountered (optional optimization, see `references/image-optimization.md`)3435### Implement new SwiftUI feature36- Design data flow first: identify owned vs injected state37- Structure views for optimal diffing (extract subviews early)38- Apply correct animation patterns (implicit vs explicit, transitions)39- Use `Button` for all tappable elements; add accessibility grouping and labels40- Gate version-specific APIs with `#available` and provide fallbacks4142### Record a new Instruments trace43Trigger when the user asks to "record a trace", "profile the app", "capture a session", etc. Full reference: `references/trace-recording.md`.44451. **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:46```bash47python3 "${SKILL_DIR}/scripts/record_trace.py" --list-devices48```492. **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`.503. **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:51```bash52python3 "${SKILL_DIR}/scripts/record_trace.py" \53--device "<name|udid>" --attach "<AppName>" \54--stop-file /tmp/stop-trace --output ~/Desktop/session.trace55```56For interactive sessions, just tell the user to press Ctrl+C when done.574. **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.585. **Analyse** the resulting trace (flow into the "Trace-driven improvement" workflow below).5960### Trace-driven improvement (Instruments `.trace` provided)61Trigger 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.6263Full reference: `references/trace-analysis.md`. Summary of the composition pattern:64651. **Scope the analysis.** Ask yourself: does the user want the whole trace, or a slice?66- "focus on X / after X / between X and Y / during X" → **resolve to a window first** (see step 2).67- No scoping cue → analyse the whole trace.682. **Resolve a window (only if the user scoped).** The parser exposes two discovery modes:69```bash70# Find a log that marks the start/end of the region of interest:71python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <path> \72--list-logs --log-message-contains "loaded feed" --log-limit 573# Or list os_signpost intervals (paired begin/end), filterable by name:74python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <path> \75--list-signposts --signpost-name-contains "ImageDecode"76```77Both modes accept `--window START_MS:END_MS` to scope discovery. Pick the `time_ms` (for logs) or `start_ms`/`end_ms` (for signposts) that match the user's description. Build a window like `--window 10400:11700`.783. **Run the main analysis** (with or without `--window`):79```bash80python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <path> \81--json-only --top 10 [--window START_MS:END_MS]82```834. **Interpret with `references/trace-analysis.md`** — key diagnostics:84- `main_running_coverage_pct` inside each correlation (<25% = blocked; ≥75% = CPU-bound).85- `swiftui-causes.top_sources` reveals *why* updates keep happening — high-edge-count sources like `UserDefaultObserver.send()` or wide `EnvironmentWriter` entries are structural invalidation bugs. Fixing one often collapses many downstream hot views.865. **When a specific view shows as expensive, ask who's invalidating it.** Use `--fanin-for "<view name>"` to get the ranked list of source nodes driving the updates.876. **Optionally ground in source.** If the user pointed at a file, read it and match view names / user-code symbols against identifiers there. If not, recommend which files to open based on the view names SwiftUI reported.887. **Return a prioritised plan.** Cite evidence (coverage %, hot symbol, overlapping view, log timestamp, cause-graph edges) and route each recommendation to a Topic Router reference.898. Only edit code if the user asked for edits.9091### Topic Router9293Consult the reference file for each topic relevant to the current task:9495| Topic | Reference |96|-------|-----------|97| State management | `references/state-management.md` |98| View composition | `references/view-structure.md` |99| Performance | `references/performance-patterns.md` |100| Lists and ForEach | `references/list-patterns.md` |101| Layout | `references/layout-best-practices.md` |102| Sheets and navigation | `references/sheet-navigation-patterns.md` |103| ScrollView | `references/scroll-patterns.md` |104| Focus management | `references/focus-patterns.md` |105| Animations (basics) | `references/animation-basics.md` |106| Animations (transitions) | `references/animation-transitions.md` |107| Animations (advanced) | `references/animation-advanced.md` |108| Accessibility | `references/accessibility-patterns.md` |109| Swift Charts | `references/charts.md` |110| Charts accessibility | `references/charts-accessibility.md` |111| Image optimization | `references/image-optimization.md` |112| Liquid Glass (iOS 26+) | `references/liquid-glass.md` |113| macOS scenes | `references/macos-scenes.md` |114| macOS window styling | `references/macos-window-styling.md` |115| macOS views | `references/macos-views.md` |116| Text patterns | `references/text-patterns.md` |117| Deprecated API lookup | `references/latest-apis.md` |118| Instruments trace analysis | `references/trace-analysis.md` |119| Instruments trace recording | `references/trace-recording.md` |120121## Correctness Checklist122123These are hard rules -- violations are always bugs:124125- [ ] `@State` properties are `private`126- [ ] `@Binding` only where a child modifies parent state127- [ ] Passed values never declared as `@State` or `@StateObject` (they ignore updates)128- [ ] `@StateObject` for view-owned objects; `@ObservedObject` for injected129- [ ] iOS 17+: `@State` with `@Observable`; `@Bindable` for injected observables needing bindings130- [ ] `ForEach` uses stable identity (never `.indices` for dynamic content)131- [ ] Constant number of views per `ForEach` element132- [ ] `.animation(_:value:)` always includes the `value` parameter133- [ ] `@FocusState` properties are `private`134- [ ] No redundant `@FocusState` writes inside tap gesture handlers on `.focusable()` views135- [ ] iOS 26+ APIs gated with `#available` and fallback provided136- [ ] `import Charts` present in files using chart types137138## References139140- `references/latest-apis.md` -- **Read first for every task.** Deprecated-to-modern API transitions (iOS 15+ through iOS 26+)141- `references/state-management.md` -- Property wrappers, data flow, `@Observable` migration142- `references/view-structure.md` -- View extraction, container patterns, `@ViewBuilder`143- `references/performance-patterns.md` -- Hot-path optimization, update control, `_logChanges()`144- `references/list-patterns.md` -- ForEach identity, Table (iOS 16+), inline filtering pitfalls145- `references/layout-best-practices.md` -- Layout patterns, GeometryReader alternatives146- `references/accessibility-patterns.md` -- VoiceOver, Dynamic Type, grouping, traits147- `references/animation-basics.md` -- Implicit/explicit animations, timing, performance148- `references/animation-transitions.md` -- View transitions, `matchedGeometryEffect`, `Animatable`149- `references/animation-advanced.md` -- Phase/keyframe animations (iOS 17+), `@Animatable` macro (iOS 26+)150- `references/charts.md` -- Swift Charts marks, axes, selection, styling, Chart3D (iOS 26+)151- `references/charts-accessibility.md` -- Charts VoiceOver, Audio Graph, fallback strategies152- `references/sheet-navigation-patterns.md` -- Sheets, NavigationSplitView, Inspector153- `references/scroll-patterns.md` -- ScrollViewReader, programmatic scrolling154- `references/focus-patterns.md` -- Focus state, focusable views, focused values, default focus, common pitfalls155- `references/image-optimization.md` -- AsyncImage, downsampling, caching156- `references/liquid-glass.md` -- iOS 26+ Liquid Glass effects and fallback patterns157- `references/macos-scenes.md` -- Settings, MenuBarExtra, WindowGroup, multi-window158- `references/macos-window-styling.md` -- Toolbar styles, window sizing, Commands159- `references/macos-views.md` -- HSplitView, Table, PasteButton, AppKit interop160- `references/text-patterns.md` -- Text initializer selection, verbatim vs localized161- `references/trace-analysis.md` -- Parse Instruments `.trace` files via `scripts/analyze_trace.py`; interpret main-thread coverage, high-severity SwiftUI updates, hitch narratives, and map findings back to source files162- `references/trace-recording.md` -- Record a new trace via `scripts/record_trace.py`: attach to a running app, launch one fresh, or capture a manually-stopped session; supports stop-file for agent-driven flows163