body: what it is, the View computed property in SwiftUI

Author: IT Sectr Published: 2026-06-24 Reading time: 7 min

The body property is the central element of the View protocol in SwiftUI, determining what content is displayed on the screen. According to Apple Developer Documentation, 2024, body is the only required requirement of the View protocol and returns some type that conforms to the same protocol. SwiftUI calls body with every state change to build and compare a new tree of elements.

Key Takeaways

  • body is a computed property required for all types that implement the View protocol
  • some View is an opaque return type that allows SwiftUI to optimize rendering
  • body is called with every state change but must not have side effects
  • ViewBuilder implicitly wraps body if it returns multiple elements
  • body is not called if the View identity and state have not changed

What is body in SwiftUI?

body is a computed property that is the only required requirement of the View protocol. Every structure conforming to View must implement body. The property returns the content that SwiftUI displays on the screen — it can be text, an image, a button, a container with nested elements, or any other type conforming to the View protocol.

The body signature is always fixed: var body: some View { get }. The return type is some View (an opaque type), not a concrete type. This means different Views may return different concrete types in body, but the Swift compiler fixes the concrete type for each implementation at compile time.

According to WWDC 2022, body is the entry point for declarative interface description. Unlike UIKit, where you imperatively create and configure UIView, in SwiftUI you declaratively describe what should be displayed, and SwiftUI itself figures out how to implement it.

body as a pure function

body should behave as a pure function — with the same inputs (structure properties and state) it should return the same View tree. If body depends on external mutable state (global variables, UserDefaults without the @AppStorage wrapper), the behavior becomes unpredictable, and SwiftUI may redraw the screen incorrectly.

How the body computed property works

The computed property body does not store a value — it is computed each time it is accessed. When SwiftUI determines that the state has changed, it recreates the View structure and reads the new body value to get the current element tree for display.

swift
struct CounterView: View {
    @State private var count = 0

    var body: some View {
        VStack {
            Text("Counter: \(count)")
                .font(.largeTitle)
            Button("Increment") {
                count += 1
            }
            .padding()
            .background(.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
        }
    }
}

In this example, body returns a VStack containing a Text and a button with modifiers. When the button is pressed, the @State property count increments, SwiftUI recreates the CounterView structure and calls body again to get the updated tree with the new Text value.

Modifiers (.font, .padding, .background, .foregroundColor, .cornerRadius) do not modify the original View but wrap it in ModifiedContent — a new type that adds the modification. Each modifier creates another nesting level, which is important to consider for performance.

body and the some View opaque type

some View in the body return type is not just a convention but a compiler requirement. Swift requires that all return paths in body have the same concrete type. Without @ViewBuilder you cannot return Text in one branch and Button in another — the compiler will produce an error.

swift
struct ConditionalView: View {
    var isReady: Bool

    @ViewBuilder
    var body: some View {
        if isReady {
            Text("Ready")
                .foregroundColor(.green)
        } else {
            ProgressView()
        }
    }
}

@ViewBuilder on body allows using conditional logic (if/else, switch) without compiler errors. ViewBuilder automatically wraps different branches in ConditionalContent — a special type that hides concrete type differences. This is a key capability for building dynamic interfaces.

Without @ViewBuilder the compiler tries to infer a single type for all return paths. If the types differ — an error occurs. This is why SwiftUI implicitly applies @ViewBuilder to body in View declarations, although in user code you need to explicitly add the annotation for custom methods and properties that return multiple Views.

Performance of some View

Using some View instead of a concrete type does not reduce performance — the compiler knows the exact type at compile time and generates direct code without dynamic dispatch. AnyView, on the contrary, uses type erasure with the overhead of wrapping in an existential container.

Body lifecycle: when and how it is called

body is called by SwiftUI in three main scenarios: when the View is first displayed, when @State/@Binding/@ObservedObject/@StateObject changes, and when the parent View passes new values through the initializer. SwiftUI may also call body when environment values (@Environment) change.

The frequency of body calls should not concern you — SwiftUI optimizes redrawing through the identity mechanism. Each View in the hierarchy has a unique identifier. If the identity and input data have not changed — body is not called even if the parent View redraws. This is achieved through Equatable comparison and structural stability.

swift
struct ParentView: View {
    var body: some View {
        ChildView(name: "Alice") // Stable identity
    }
}

struct ChildView: View {
    let name: String
    var body: some View {
        Text("Hello, \(name)!")
    }
}

In this example, if ParentView redraws but passes the same name value — ChildView.body is not called. SwiftUI compares the structure's input data and, if unchanged, skips the child component's redraw. This is the view differentiation mechanism.

When body is called unexpectedly

There are several pitfalls leading to unexpected body calls: using classes without ObservableObject, passing closures created inside body (each closure creation yields a new identity), and incorrect use of EquatableView. If body is called too often — check the identity stability of all child components.

Best practices for working with body

First rule: body should be minimal. Move complex logic into separate computed properties or methods that return View. This improves readability and allows SwiftUI to more accurately determine which parts of the hierarchy have changed. Break large bodies into subcomponents with clear responsibility boundaries.

Second rule: do not use body to perform work. Data loading, network operations, database writes — all of this should happen outside body, in tasks, onChange modifiers, or through ObservableObject. body is intended solely for interface declaration.

Third rule: use the EquatableView property or a custom Equatable protocol for Views if the standard structural comparison is insufficient. This allows you to explicitly tell SwiftUI when a child View needs a redraw and avoid unnecessary body calls.

Fourth rule: if body contains complex computations (formatting, filtering, sorting) — use @State for caching the result or move computations to a separate method called from onChange. Repeated computations in body with every state update is a common cause of animation lag.

Fifth rule: for lists (List, ForEach) ensure stable identifiers via the id parameter. Without stable identity, ForEach recreates all elements on any change, calling body for each of them, even if only one element changed.

Frequently Asked Questions

What is body in SwiftUI?

body is the computed property of the View protocol that returns content for display. It is the only required requirement of the protocol. The return type is some View, which allows SwiftUI to optimize the hierarchy at compile time.

Can body be called multiple times?

Yes, SwiftUI calls body with every state change (@State, @Binding, @ObservedObject) or input data change. This is normal behavior for a declarative framework. SwiftUI optimizes call frequency through the identity mechanism and Equatable comparison.

Why does body return some View instead of a concrete type?

some View is an opaque type that hides the concrete implementation. The compiler fixes the type at compile time, ensuring direct call performance. This provides flexibility: you can change the return type without changing the signature.

Can I return nil from body?

No, body cannot be optional — the return type some View does not allow nil. If you need to hide an element conditionally, use conditional logic inside @ViewBuilder or return EmptyView, which takes no space in the hierarchy.

Does the number of modifiers affect body performance?

Each modifier creates a new ModifiedContent layer, increasing the hierarchy depth. For most screens (up to 50 modifiers) the impact is negligible. Excessive modifier count (hundreds) may slow down diffing. Group related modifiers into custom extensions.

Summary

  • body is the required computed property of the View protocol that defines the screen content
  • some View is an opaque return type that hides the concrete implementation from calling code
  • @ViewBuilder is implicitly applied to body to support conditional logic and multiple elements
  • body must not contain side effects — it is a pure interface declaration
  • SwiftUI optimizes body calls through the identity mechanism and Equatable comparison
  • Break down large bodies into subcomponents for better performance and readability
  • AnyView increases overhead — use @ViewBuilder and Group instead of type erasure

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also