Spatial SwiftUI: Volume TabViews

SwiftUI TabViews are presented as Ornaments at the front leading anchor of the volume.

Overview

We can add tab views to volumes just like we can with windows. We define a view, then add the tapItem modifier.

 TabView {
    RealityView { content in ... }
        .tabItem {
            Image(systemName: "circle.fill")
            Text("Sphere")
        }

    RealityView { content in ... }
        .tabItem {
            Image(systemName: "rectangle.fill")
            Text("Box")
        }

    RealityView { content in ... }
        .tabItem {
            Image(systemName: "capsule.fill")
            Text("Cylynder")
        }
}

The tab controls are placed in the front leading position of the volume. We should be mindful not to place other ornaments near that location.

Tab control at the front leading anchor of a volume.
Tab control at the front leading anchor of a volume.

This example has three tabs that load three RealityViews. Interesting, SwiftUI seems to load each scene only once. Watch the video below and pay attention to the log on the right.

Video Demo

Full Example Code

struct Example048: View {
    @State private var logEntries: [String] = []
    
    var body: some View {
        TabView {
            RealityView { content in
                let model = ModelEntity(
                    mesh: .generateSphere(radius: 0.1),
                    materials: [SimpleMaterial(color: .stepRed, isMetallic: false)])
                content.add(model)
                logEntries.append("Sphere created \(Date())")
            }

            .tabItem {
                Image(systemName: "circle.fill")
                Text("Sphere")
            }

            RealityView { content in
                let model = ModelEntity(
                    mesh: .generateBox(size: 0.2, cornerRadius: 0.05),
                    materials: [SimpleMaterial(color: .stepBlue, isMetallic: false)])
                content.add(model)
                logEntries.append("Box created \(Date())")
            }

            .tabItem {
                Image(systemName: "rectangle.fill")
                Text("Box")
            }

            RealityView { content in
                let model = ModelEntity(
                    mesh: .generateCylinder(height: 0.2, radius: 0.1),
                    materials: [SimpleMaterial(color: .stepGreen, isMetallic: false)])
                content.add(model)
                logEntries.append("Cylynder created \(Date())")
            }
            .tabItem {
                Image(systemName: "capsule.fill")
                Text("Cylynder")
            }

        }
        .ornament(attachmentAnchor: .scene(.trailing)) {
            List(logEntries, id: \.self) { entry in
                Text(entry)
                    .fontDesign(.monospaced)
            }
            .listStyle(.plain)
            .frame(width: 300, height: 600)
            .glassBackgroundEffect()
        }
    }
}

Support our work so we can continue to bring you new examples and articles.

Download the Xcode project with this and many more examples from Step Into Vision.
Some examples are provided as standalone Xcode projects. You can find those here.

Questions or feedback?