Skip to content
Result Builders
step 1/4

Reading — step 1 of 4

Learn

~1 min readBuilders and Opaque Types

Result builders are how SwiftUI's view DSL works:

VStack {
    Text("Hello")
    Image("icon")
    Button("Tap") { ... }
}

The block is processed by a result builder that combines each statement into a single result.

Defining a builder:

@resultBuilder
struct StringBuilder {
    static func buildBlock(_ components: String...) -> String {
        components.joined(separator: " ")
    }
}

@StringBuilder
func greeting() -> String {
    "Hello,"
    "world!"
    "How are you?"
}

print(greeting())   // "Hello, world! How are you?"

The @StringBuilder annotation tells the compiler: pass each statement of the function body to buildBlock.

Optional and conditional support:

@resultBuilder
struct StringBuilder {
    static func buildBlock(_ components: String...) -> String {
        components.joined(separator: " ")
    }
    static func buildOptional(_ component: String?) -> String {
        component ?? ""
    }
    static func buildEither(first: String) -> String { first }
    static func buildEither(second: String) -> String { second }
}

@StringBuilder
func message(formal: Bool) -> String {
    "Greetings,"
    if formal {
        "esteemed friend."
    } else {
        "dude."
    }
}

The builder's buildEither and buildOptional methods handle if / if-else and if let.

Result builder methods (implement only what you need):

  • buildBlock(_:) — required; merges statements
  • buildOptional(_:)if (no else)
  • buildEither(first:), buildEither(second:)if/else
  • buildArray(_:)for loops
  • buildExpression(_:) — pre-process individual expressions
  • buildFinalResult(_:) — final transform

Where used:

  • SwiftUI views
  • Server-side Vapor's XCTAssert* builders
  • Plot HTML/CSS/JS builders
  • Regex Builders (Swift 5.7+)

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…