Agent SkillsAFK-surf/OpenBridge › swiftui-view-refactor

swiftui-view-refactor

GitHub

用于重构和审查 SwiftUI 视图文件,确保结构一致、依赖注入合理及 Observation 正确使用。指导视图排序、MV 模式应用、大视图拆分及稳定视图树构建。

.agents/skills/swiftui-view-refactor/SKILL.md AFK-surf/OpenBridge

Trigger Scenarios

清理 SwiftUI 视图布局或顺序 安全处理 ViewModels 标准化依赖和 @Observable 状态初始化

Install

npx skills add AFK-surf/OpenBridge --skill swiftui-view-refactor -g -y
More Options

Non-standard path

npx skills add https://github.com/AFK-surf/OpenBridge/tree/main/.agents/skills/swiftui-view-refactor -g -y

Use without installing

npx skills use AFK-surf/OpenBridge@swiftui-view-refactor

指定 Agent (Claude Code)

npx skills add AFK-surf/OpenBridge --skill swiftui-view-refactor -a claude-code -g -y

安装 repo 全部 skill

npx skills add AFK-surf/OpenBridge --all -g -y

预览 repo 内 skill

npx skills add AFK-surf/OpenBridge --list

SKILL.md

Frontmatter
{
    "name": "swiftui-view-refactor",
    "description": "Refactor and review SwiftUI view files for consistent structure, dependency injection, and Observation usage. Use when asked to clean up a SwiftUI view’s layout\/ordering, handle view models safely (non-optional when possible), or standardize how dependencies and @Observable state are initialized and passed."
}

SwiftUI View Refactor

Overview

Apply a consistent structure and dependency pattern to SwiftUI views, with a focus on ordering, Model-View (MV) patterns, careful view model handling, and correct Observation usage.

Core Guidelines

1) View ordering (top → bottom)

  • Environment
  • private/public let
  • @State / other stored properties
  • computed var (non-view)
  • init
  • body
  • computed view builders / other view helpers
  • helper / async functions

2) Prefer MV (Model-View) patterns

  • Default to MV: Views are lightweight state expressions; models/services own business logic.
  • Favor @State, @Environment, @Query, and task/onChange for orchestration.
  • Inject services and shared models via @Environment; keep views small and composable.
  • Split large views into subviews rather than introducing a view model.

3) Split large bodies and view properties

  • If body grows beyond a screen or has multiple logical sections, split it into smaller subviews.
  • Extract large computed view properties (var header: some View { ... }) into dedicated View types when they carry state or complex branching.
  • It's fine to keep related subviews as computed view properties in the same file; extract to a standalone View struct only when it structurally makes sense or when reuse is intended.
  • Prefer passing small inputs (data, bindings, callbacks) over reusing the entire parent view state.

Example (extracting a section):

var body: some View {
    VStack(alignment: .leading, spacing: 16) {
        HeaderSection(title: title, isPinned: isPinned)
        DetailsSection(details: details)
        ActionsSection(onSave: onSave, onCancel: onCancel)
    }
}

Example (long body → shorter body + computed views in the same file):

var body: some View {
    List {
        header
        filters
        results
        footer
    }
}

private var header: some View {
    VStack(alignment: .leading, spacing: 6) {
        Text(title).font(.title2)
        Text(subtitle).font(.subheadline)
    }
}

private var filters: some View {
    ScrollView(.horizontal, showsIndicators: false) {
        HStack {
            ForEach(filterOptions, id: \.self) { option in
                FilterChip(option: option, isSelected: option == selectedFilter)
                    .onTapGesture { selectedFilter = option }
            }
        }
    }
}

Example (extracting a complex computed view):

private var header: some View {
    HeaderSection(title: title, subtitle: subtitle, status: status)
}

private struct HeaderSection: View {
    let title: String
    let subtitle: String?
    let status: Status

    var body: some View {
        VStack(alignment: .leading, spacing: 4) {
            Text(title).font(.headline)
            if let subtitle { Text(subtitle).font(.subheadline) }
            StatusBadge(status: status)
        }
    }
}

3b) Keep a stable view tree (avoid top-level conditional view swapping)

  • Avoid patterns where a computed view (or body) returns completely different root branches using if/else.
  • Prefer a single stable base view, and place conditions inside sections/modifiers (overlay, opacity, disabled, toolbar, row content, etc.).
  • Root-level branch swapping can cause identity churn, broader invalidation, and extra recomputation in SwiftUI.

Prefer:

var body: some View {
    List {
        documentsListContent
    }
    .toolbar {
        if canEdit {
            editToolbar
        }
    }
}

Avoid:

var documentsListView: some View {
    if canEdit {
        editableDocumentsList
    } else {
        readOnlyDocumentsList
    }
}

4) View model handling (only if already present)

  • Do not introduce a view model unless the request or existing code clearly calls for one.
  • If a view model exists, make it non-optional when possible.
  • Pass dependencies to the view via init, then pass them into the view model in the view's init.
  • Avoid bootstrapIfNeeded patterns.

Example (Observation-based):

@State private var viewModel: SomeViewModel

init(dependency: Dependency) {
    _viewModel = State(initialValue: SomeViewModel(dependency: dependency))
}

5) Observation usage

  • For @Observable reference types, store them as @State in the root view.
  • Pass observables down explicitly as needed; avoid optional state unless required.

Workflow

  1. Reorder the view to match the ordering rules.
  2. Favor MV: move lightweight orchestration into the view using @State, @Environment, @Query, task, and onChange.
  3. Ensure stable view structure: avoid top-level if-based branch swapping; move conditions to localized sections/modifiers.
  4. If a view model exists, replace optional view models with a non-optional @State view model initialized in init by passing dependencies from the view.
  5. Confirm Observation usage: @State for root @Observable view models, no redundant wrappers.
  6. Keep behavior intact: do not change layout or business logic unless requested.

Notes

  • Prefer small, explicit helpers over large conditional blocks.
  • Keep computed view builders below body and non-view computed vars above init.
  • For MV-first guidance and rationale, see references/mv-patterns.md.

Large-view handling

  • When a SwiftUI view file exceeds ~300 lines, split it using extensions to group related helpers. Move async functions and helper functions into dedicated private extensions, separated with // MARK: - comments that describe their purpose (e.g., // MARK: - Actions, // MARK: - Subviews, // MARK: - Helpers). Keep the main struct focused on stored properties, init, and body, with view-building computed vars also grouped via marks when the file is long.

Version History

  • a9ca905 Current 2026-07-24 11:34

Same Skill Collection

.agents/skills/app-store-changelog/SKILL.md
.agents/skills/bridge-agent-log-analyzer/SKILL.md
.agents/skills/gh-issue-fix-flow/SKILL.md
.agents/skills/github/SKILL.md
.agents/skills/react-component-performance/SKILL.md
.agents/skills/swift-concurrency-expert/SKILL.md
.agents/skills/swift-testing-expert/SKILL.md
.agents/skills/swiftui-expert-skill/SKILL.md
.agents/skills/swiftui-performance-audit/SKILL.md
.agents/skills/swiftui-ui-patterns/SKILL.md
macos/OpenBridge/Resources/SystemSkills.bundle/format-converter/SKILL.md
macos/OpenBridge/Resources/SystemSkills.bundle/github/SKILL.md
macos/OpenBridge/Resources/SystemSkills.bundle/linear/SKILL.md
macos/OpenBridge/Resources/SystemSkills.bundle/skill-manager/SKILL.md
macos/OpenBridge/Resources/SystemSkills.bundle/ui-designer/SKILL.md
.agents/skills/swift-concurrency/SKILL.md
macos/OpenBridge/Resources/SystemSkills.bundle/docs/SKILL.md
macos/OpenBridge/Resources/SystemSkills.bundle/pdfs/SKILL.md
macos/OpenBridge/Resources/SystemSkills.bundle/spreadsheets/SKILL.md

Metadata

Files
0
Version
a9ca905
Hash
3f9b8438
Indexed
2026-07-24 11:34

Главная - Вики-сайт
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-06 19:38
浙ICP备14020137号-1 $Гость$