Result builders (formerly known as function builders) are a powerful Swift feature that enables you to create elegant domain-specific languages (DSLs). They're the magic behind SwiftUI's declarative syntax and can be used to build your own custom DSLs. This is an advanced Swift feature (requires Swift 5.4+; platform availability depends on the APIs you use, such as SwiftUI). Familiarity with generics and protocols is recommended.

What are Result Builders?

Result builders are types annotated with @resultBuilder that transform multiple statements into a single combined result. They enable natural, declarative syntax for constructing complex values.

Basic Result Builder

Here's a simple result builder for building strings:

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

@StringBuilder
func makeGreeting() -> String {
    "Hello"
    "World"
    "from Swift!"
}

print(makeGreeting())
// Output:
// Hello
// World
// from Swift!

Supporting Control Flow

Add support for if statements:

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

    static func buildOptional(_ component: String?) -> String {
        component ?? ""
    }

    static func buildEither(first component: String) -> String {
        component
    }

    static func buildEither(second component: String) -> String {
        component
    }
}

@HTMLBuilder
func buildPage(isLoggedIn: Bool) -> String {
    "<html>"
    "<body>"
    if isLoggedIn {
        "<h1>Welcome back!</h1>"
    } else {
        "<h1>Please log in</h1>"
    }
    "</body>"
    "</html>"
}

Supporting Arrays and Loops

Add support for for loops:

extension HTMLBuilder {
    static func buildArray(_ components: [String]) -> String {
        components.joined()
    }
}

@HTMLBuilder
func buildList(items: [String]) -> String {
    "<ul>"
    for item in items {
        "<li>\(item)</li>"
    }
    "</ul>"
}

Real-World Example: URL Builder

Here's a practical result builder for constructing URLs:

@resultBuilder
struct URLComponentBuilder {
    static func buildBlock(_ components: URLQueryItem...) -> [URLQueryItem] {
        components
    }

    static func buildOptional(_ component: [URLQueryItem]?) -> [URLQueryItem] {
        component ?? []
    }

    static func buildArray(_ components: [[URLQueryItem]]) -> [URLQueryItem] {
        components.flatMap { $0 }
    }
}

struct URLBuilder {
    let baseURL: URL

    func build(@URLComponentBuilder _ builder: () -> [URLQueryItem]) -> URL? {
        var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: true)
        components?.queryItems = builder()
        return components?.url
    }
}

// Usage
let builder = URLBuilder(baseURL: URL(string: "https://api.example.com/search")!)
let url = builder.build {
    URLQueryItem(name: "q", value: "swift")
    URLQueryItem(name: "limit", value: "10")
    if includeImages {
        URLQueryItem(name: "images", value: "true")
    }
}

Custom View Builder

Create a custom view-like builder:

protocol View {
    var body: String { get }
}

@resultBuilder
struct ViewBuilder {
    static func buildBlock(_ components: View...) -> [View] {
        components
    }
}

struct Text: View {
    let content: String
    var body: String { "<p>\(content)</p>" }
}

struct VStack: View {
    let children: [View]

    init(@ViewBuilder content: () -> [View]) {
        self.children = content()
    }

    var body: String {
        "<div>\(children.map { $0.body }.joined())</div>"
    }
}

// Usage
let view = VStack {
    Text("Hello")
    Text("World")
}

Use Cases

Result builders are perfect for:

  • Creating DSLs for configuration

  • Building HTML/XML

  • Constructing complex data structures

  • Query builders

  • Test specifications

  • Custom UI frameworks

Wrap up

Result builders enable elegant, declarative APIs in Swift. Understanding how they work helps you use SwiftUI more effectively and create your own domain-specific languages.

Resources:

Keep reading

Read more

6 min read SwiftUI ViewModifiers Read article 5 min read What is @MainActor Read article 10 min read Voice Control Read article

Share

Share this article

Share Bluesky Mastodon Twitter LinkedIn Facebook