View Composition Rules
@ViewBuilder Computed Properties
Every meaningful section of a view should be a @ViewBuilder computed property:
struct TaskListView: View {
var body: some View {
NavigationStack {
VStack {
headerView
taskList
addButton
}
}
}
private var headerView: some View {
Text("My Tasks")
.font(AppTheme.Fonts.largeTitle)
.padding()
}
private var taskList: some View {
List(tasks) { task in
TaskRow(task: task)
}
}
private var addButton: some View {
Button("Add Task") {
showAddSheet = true
}
.buttonStyle(.borderedProminent)
}
}
Size Guidelines
- Each computed property: 15-40 lines
- If a section exceeds 40 lines, extract it to a separate struct
- If a section is reused in multiple views, extract to a separate file
Section Naming Pattern
Use descriptive suffixes:
headerSection,headerView— top areacontentSection,contentView— main contentfooterSection— bottom area{feature}Section— feature-specific (e.g.,profileSection,statsSection){action}Button— action buttons (e.g.,addButton,saveButton)
When to Extract to Separate Struct
Extract a section into its own View struct when:
- It exceeds 40 lines of code
- It's reused across multiple views
- It has its own state (needs
@Stateor@Binding) - It represents a distinct UI component (e.g., a card, a row)
Body Should Only Contain Property References
The body property should be a composition of computed properties — not raw implementation:
// Good — body is a clear outline
var body: some View {
ScrollView {
headerSection
featureCards
recentActivity
}
}
// Bad — body contains raw implementation
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("Welcome")
.font(AppTheme.Fonts.largeTitle)
// ... 50 more lines
}
}
}
微信扫一扫