🎯

swiftui-view-refactor

🎯Skill

from steipete/agent-scripts

VibeIndex|
What it does

Refactors SwiftUI views to improve structure, dependency injection, and Observation usage with consistent patterns and best practices.

πŸ“¦

Part of

steipete/agent-scripts(16 items)

swiftui-view-refactor

Installation

πŸ“‹ No install commands found in docs. Showing default command. Check GitHub for actual instructions.
Quick InstallInstall with npx
npx skills add steipete/agent-scripts --skill swiftui-view-refactor
16Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

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.

Overview

# SwiftUI View Refactor

_Attribution: copied from @Dimillian’s Dimillian/Skills (2025-12-31)._

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):

```swift

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):

```swift

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):

```swift

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)

}

}

}

```

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):

```swift

@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) 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.

4) Confirm Observation usage: @State for root @Observable view models, no redundant wrappers.

5) 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.