swiftui · essay · architecture · state

How to Structure a SwiftUI View File (A Beginner’s Guide)

Published March 2, 2026 · 4 min read · beginner

The confusion

For many people starting with SwiftUI, writing the code itself is not the hardest part.

The real struggle is structure.

Questions like these come up quickly:

  • Where do @Binding and @State properties belong?
  • What goes inside body, and what should not?
  • Where do helper methods go?
  • Why does everyone seem to structure files differently?

Without a mental model, SwiftUI files slowly turn into long, messy blocks of code.


Why this is confusing

SwiftUI does not enforce structure.

A view is “just” a struct, and Swift allows you to put things almost anywhere:

  • properties
  • computed values
  • methods
  • nested types

That freedom is powerful, but for beginners it removes guidance.

Without conventions, it is easy to mix:

  • state and logic
  • UI description and behavior
  • data ownership and data access

The result is code that works, but is hard to read and harder to change.


A better mental model

A simple and reliable mental model is this:

A SwiftUI view file is a document with sections.
Each section has exactly one responsibility.

Think of a view file in this order:

  1. Inputs (what the view needs)
  2. Internal state (what the view owns)
  3. The UI description (body)
  4. Behavior (helper methods)

Keeping this order makes SwiftUI code predictable and easy to scan.


A structured example

Here is a clean, beginner-friendly structure:

struct ProfileView: View {

    // MARK: - Inputs
    @Binding var username: String

    // MARK: - State
    @State private var isEditing = false

    // MARK: - Body
    var body: some View {
        VStack(spacing: 12) {
            Text(username)

            if isEditing {
                Text("Editing mode")
            }

            Button(isEditing ? "Done" : "Edit") {
                toggleEditing()
            }
        }
    }

    // MARK: - Actions
    private func toggleEditing() {
        isEditing.toggle()
    }
}

Nothing here is complex. The clarity comes purely from structure.


Inputs: bindings and constants

Inputs describe what the view needs from the outside.

Typical examples:

  • @Binding
  • constant values like IDs or titles

Rules of thumb:

  • Inputs come first
  • Inputs never own state
  • Inputs should not be mutated directly (unless they are bindings)

This makes ownership boundaries obvious.


State: what the view owns

State represents data owned by the view itself.

Typical examples:

  • @State
  • local UI flags
  • temporary values

Rules of thumb:

  • State is private
  • State lives above the body
  • If multiple views need it, it probably does not belong here

State answers the question:

“What can this view change by itself?”


The body: describing the UI

The body is the heart of a SwiftUI view.

Important rules:

  • body describes what the UI looks like
  • it should stay cheap
  • it should avoid side effects

Good body code reads like a layout description, not like a script.

If logic grows, move it out.


Methods: behavior and intent

Helper methods describe how the view reacts to interaction.

Examples:

  • button actions
  • small transformations
  • intent-revealing behavior

Best practices:

  • place methods below body
  • keep them private
  • give them descriptive names

Methods help keep body readable.


Why this structure scales

This structure works because it matches SwiftUI’s design:

  • inputs define dependencies
  • state defines ownership
  • body defines description
  • methods define behavior

As views grow, this separation prevents chaos.

You can open any file and immediately answer:

  • What does this view need?
  • What does it own?
  • What does it show?
  • What can it do?

One sentence to remember

Structure your SwiftUI views by responsibility:
inputs first, state second, UI in body, behavior last.

That alone makes SwiftUI code dramatically easier to read and maintain.

Next steps

If you want to apply this structure in real components, these two pieces are the most direct continuation:

Tags: SwiftUI · Basics · Architecture