跳转至
Structure

SceneBuilder

A property wrapper that lets you build scenes declaratively.

Declaration

@\_functionBuilder struct SceneBuilder

Overview

SceneBuilder is used primary in the App structure in SwiftUI to let you create your app's scenes by just listing them out in a trailing closure. It's a property wrapper applied to function parameter. Usually, it's just working behind the scenes, so you don't have to worry about it.

(A scene builder is just specific type of result builder that you can use with Scenes. Check out that link to learn more about using these to write clean code.)

Using a SceneBuilder as a trailing closure

SceneBuilder works behind the scenes of many common SwiftUI scenes - like WindowGroup and Settings. For example, here is the declaration of Group's initializer:

public init(@SceneBuilder content: () -> Content) {
    // Implementation here
}
Since that parameter is a SceneBuilder, you can easily create a Group by passing it a trailing closure stacking views:

@main
struct SampleApp: App {
    var body: some Scene {
        Group {
            WindowGroup(id: "a") {
                Text("I'm in the group 😁")
            }
            WindowGroup(id: "b") {
                Text("Me too 🥂")
            }
        }
    }
}

Using a SceneBuilder as a function

You can also use SceneBuilder as a function. Just tag your function with @SceneBuilder, and use it just like you would with a trailing closure:

@main
struct SampleApp: App {
    var body: some Scene {
        Group(content: contentBuilder)
    }

    @SceneBuilder
    func contentBuilder() -> some Scene {
        WindowGroup(id: "a") {
            Text("I'm in the group 😁")
        }
        WindowGroup(id: "b") {
            Text("Me too 🥂")
        }
    }
}

Using a SceneBuilder in your own Scenes

Exactly like Group, you can also use ScebeBuilders in your own custom scenes. Just tag the parameter of your Scene's initializer with @SceneBuilder, and anyone using your scene will be able to easily pass you views just by listing them.

In the example below, we use this technique to create a special type of Group that adds command-P to print bananas to everything. Note that SceneBuilders are actually functions, so in order to get the content they contain, you have to call the function. Below, this is done with content().

struct ContentView: View {
    var body: some View {
        BananaPrintingGroup {
            WindowGroup(id: "a") {
                Text("I print 🍌")
            }
            WindowGroup(id: "b") {
                Text("Hey same 🍌🍌🍌")
            }
        }
    }
}

struct BananaPrintingGroup<Content>: Scene where Content: Scene {
    var scenes: Content

    init(@ViewBuilder content: () -> Content) {
        self.scenes = content()
    }

    var body: some View {
        Group {
            views.commands { PrintCommand() }
        }
    }
}

struct PrintCommand: Commands {
    var body: some Commands {
        CommandMenu("Print") {
            Button("Print", action: { print("🍌") })
                .keyboardShortcut(KeyboardShortcut(KeyEquivalent("p"), modifiers: [.command]))
        }
    }
}

Availability

iOS 14.0+

macOS 11.0+

tvOS 14.0+

watchOS 7.0+

Topics


Type Method

buildBlock(_:) Passes a single scene written as a child scene through unmodified.

buildBlock(_:_:) Passes 2 scenes unmodified.

buildBlock(_:_:_:) Passes 3 scenes unmodified.

buildBlock(_:_:_:_:) Passes 4 scenes unmodified.

buildBlock(_:_:_:_:_:) Passes 5 scenes unmodified.

buildBlock(_:_:_:_:_:_:) Passes 6 scenes unmodified.

buildBlock(_:_:_:_:_:_:_:) Passes 7 scenes unmodified.

buildBlock(_:_:_:_:_:_:_:_:) Passes 8 scenes unmodified.

buildBlock(_:_:_:_:_:_:_:_:_:) Passes 9 scenes unmodified.

buildBlock(_:_:_:_:_:_:_:_:_:_:) Passes 10 scenes unmodified.