swiftui-view-refactor
Install this skill
npx skills add dimillian/skillsWorks across Claude Code, Cursor, Codex, Copilot & Antigravity
The swiftui-view-refactor skill standardizes SwiftUI architecture by enforcing strict structural, dependency, and composition rules. It moves beyond generic cleanup, prioritizing a consistent property ordering—from environment values down to view body—and modularizing bloated components. By favoring a direct Model-View relationship, it discourages unnecessary abstraction layers like bloated view models, instead promoting small subviews and functional state orchestration via @State and @Environment. When files grow past 300 lines, this skill mandates logical separation through extensions and marked regions. It ensures that business logic remains decoupled from view representation, resulting in cleaner, more maintainable code that aligns with modern Swift Observation practices. The focus remains on readability and predictability, transforming cluttered, inconsistent views into highly modular components that prioritize native SwiftUI patterns over architectural boilerplate.
When to Use This Skill
- •Cleaning up views that have grown unreadable or exceed 300 lines of code
- •Replacing legacy, complex view-model patterns with native SwiftUI state orchestration
- •Improving code review consistency across a team's view layer
- •Extracting complex UI sections into smaller, testable sub-components
How to Invoke This Skill
Example prompts that trigger this skill in Claude Code, Cursor, or Antigravity:
- “refactor this view to match SwiftUI best practices
- “clean up this bloated SwiftUI file structure
- “split this large SwiftUI body into smaller subviews
- “convert this view model to use proper dependency injection in init
- “organize this SwiftUI file using mark extensions
Pro Tips
- 💡Always run this skill after initial view development to catch structural inconsistencies early, before they become deeply ingrained.
- 💡Combine this skill with a Swift linter to enforce both structural best practices and granular Swift style guidelines simultaneously.
- 💡Prioritize injecting shared models and services via `@Environment` or direct parameters to keep views small and highly composable, strictly adhering to the MV pattern.
What this skill does
- •Enforces standardized property and method ordering within SwiftUI structs
- •Refactors monolithic bodies into granular, reusable subviews or computed properties
- •Optimizes memory by initializing non-optional view models via dependency injection
- •Organizes large view files using marked extensions for actions and helpers
- •Aligns state management with native Observable patterns
When not to use it
- ✕When a view requires minimal logic and is already under 50 lines
- ✕If the project strictly mandates an MVVM architecture that forbids raw state orchestration
Example workflow
- Analyze the current struct properties and rearrange them to follow the defined ordering standard
- Evaluate large view bodies and identify logical sections suitable for extraction into subviews
- Move isolated helper functions and action logic into private extensions with marked headers
- Replace optional or non-initialized view models with direct, dependency-injected properties
- Verify that state management uses @State or @Environment correctly without redundant wrappers
Prerequisites
- –Existing SwiftUI code
- –Understanding of the @Observable macro
- –Basic knowledge of dependency injection
Pitfalls & limitations
- !Over-extracting tiny views that increase boilerplate without improving clarity
- !Moving logic into extensions that breaks access to private view state
- !Ignoring the specific ordering rules which can lead to inconsistent diffs in version control
FAQ
How it compares
Unlike manual refactoring which is prone to inconsistency, this skill forces strict adherence to a documented architecture, ensuring every view in the project follows an identical structural pattern.
📄 Full skill instructions — original source: dimillian/skills
## 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)
}
}
}### 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) 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.## 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.How to Use This Skill Unit
Option A: Project-Specific (Recommended)
- Click "Download" above
- In your project, create the directory:
.agent/skills/swiftui-view-refactor/ - Save the file as
SKILL.md - The agent will automatically discover the skill based on its description.
Option B: Global Installation (All Agents)
Save the file to these locations to make it available across all projects:
- Claude Code:
~/.claude/skills/dimillian/skills/swiftui-view-refactor/SKILL.md - Cursor:
~/.cursor/skills/dimillian/skills/swiftui-view-refactor/SKILL.md - Antigravity:
~/.gemini/antigravity/skills/dimillian/skills/swiftui-view-refactor/SKILL.md
🚀 Install with CLI:npx skills add dimillian/skills
