Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2023 EssentialsSpatial ComputingSwiftUI & UI Frameworks

WWDC23 · 26 min · Essentials / Spatial Computing / SwiftUI & UI Frameworks

Meet SwiftUI for spatial computing

Take a tour of the solar system with us and explore SwiftUI for visionOS! Discover how you can build an entirely new universe of apps with windows, volumes, and spaces. We’ll show you how to get started with SwiftUI on this platform as we build an astronomy app, add 3D content, and create a fully immersive experience to transport people to the stars.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 19 snippets

Button swift · at 2:02 ↗
Button("Of course") {
  // perform action
}
Toggle Favorite swift · at 2:41 ↗
Toggle(isOn: $favorite) {
    Label("Favorite", systemImage: "star")
}
TabView swift · at 2:48 ↗
TabView {
    DogsTab()
        .tabItem {
            Label("Dogs", systemImage: "pawprint")
        }

    CatsTab()
        .tabItem {
            Label("Cats", image: "cat")
        }

    BirdsTab()
        .tabItem {
            Label("Birds", systemImage: "bird")
        }
}
World App swift · at 3:37 ↗
@main
struct WorldApp: App {
    var body: some Scene {
        WindowGroup("Hello, world") {
            ContentView()
        }
    }
}
World TabView swift · at 7:03 ↗
@main
struct WorldApp: App {
    var body: some Scene {
        WindowGroup("Hello, world") {
            TabView {
                Modules()
                    .tag(Tabs.menu)
                    .tabItem {
                        Label("Experience", systemImage: "globe.americas")
                    }
                FunFactsTab()
              	    .tag(Tabs.library)
                    .tabItem {
                        Label("Library", systemImage: "book")
                    }                    
            }
        }
    }
}
Stats Grid Section swift · at 8:42 ↗
VStack(alignment: .leading, spacing: 12) {
    Text("Stats")
        .font(.title)

    StatsGrid(stats: stats)
        .padding()
        .background(.regularMaterial, in: .rect(cornerRadius: 12))
}
Fun Fact Button swift · at 9:23 ↗
Button(action: {
    // perform button action
}) {
    VStack(alignment: .leading, spacing: 12) {
        Text(fact.title)
            .font(.title2)
            .lineLimit(2)
        Text(fact.details)
            .font(.body)
            .lineLimit(4)
        Text("Learn more")
            .font(.caption)
            .foregroundStyle(.secondary)
    }
    .frame(width: 180, alignment: .leading)
}
.buttonStyle(.funFact)
FunFactButtonStyle swift · at 13:15 ↗
struct FunFactButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .padding()
            .background(.regularMaterial, in: .rect(cornerRadius: 12))
            .hoverEffect()
            .scaleEffect(configuration.isPressed ? 0.95 : 1)
    }
}
Globe Volume swift · at 14:17 ↗
@main
struct WorldApp: App {
    var body: some Scene {
        WindowGroup {
            Globe()
        }
        .windowStyle(.volumetric)
        .defaultSize(width: 600, height: 600, depth: 600)
    }
}
Model3D swift · at 14:36 ↗
import SwiftUI
import RealityKit

struct Globe: View {
    var body: some View {
        Model3D(named: "Earth")
    }
}
Globe with rotation and controls swift · at 15:40 ↗
struct Globe: View {
    @State var rotation = Angle.zero
    var body: some View {
        ZStack(alignment: .bottom) {
            Model3D(named: "Earth")
                .rotation3DEffect(rotation, axis: .y)
                .onTapGesture {
                    withAnimation(.bouncy) {
                        rotation.degrees += randomRotation()
                    }
                }
                .padding3D(.front, 200)
            
            GlobeControls()
                .glassBackgroundEffect(in: .capsule)
        }
    }

    func randomRotation() -> Double {
        Double.random(in: 360...720)
    }
}
RealityView swift · at 17:30 ↗
RealityView { content in
    if let earth = try? await
        ModelEntity(named: "Earth")
    {
       earth.addImageBasedLighting()
       content.add(earth)
    }
}
RealityView Gesture swift · at 18:57 ↗
struct Earth: View {
		@State private var pinLocation: GlobeLocation?

    var body: some View {
        RealityView { content in
            if let earth = try? await
                ModelEntity(named: "Earth")
            {
               earth.addImageBasedLighting()
               content.add(earth)
            }
        }
				.gesture(
            SpatialTapGesture()
                .targetedToAnyEntity()
                .onEnded { value in
                    withAnimation(.bouncy) {
                        rotation.degrees += randomRotation()
                        animatingRotation = true
                    } completion: {
                        animatingRotation = false
                    }
                    pinLocation = lookUpLocation(at: value)
                }
        )
    }
}
RealityView Attachments swift · at 19:34 ↗
struct Earth: View {
		@State private var pinLocation: GlobeLocation?

    var body: some View {
        RealityView { content in
            if let earth = try? await
                ModelEntity(named: "Earth")
            {
               earth.addImageBasedLighting()
               content.add(earth)
            }
        } update: { content, attachments in
            if let pin = attachments.entity(for: "pin") {
                content.add(pin)
                placePin(pin)
            }
        } attachments: {
            if let pinLocation {
                GlobePin(pinLocation: pinLocation)
                    .tag("pin")
            }
        }
				.gesture(
            SpatialTapGesture()
                .targetedToAnyEntity()
                .onEnded { value in
                    withAnimation(.bouncy) {
                        rotation.degrees += randomRotation()
                        animatingRotation = true
                    } completion: {
                        animatingRotation = false
                    }
                    pinLocation = lookUpLocation(at: value)
                }
        )
    }
}
ImmersiveSpace swift · at 21:11 ↗
@main
struct WorldApp: App {
    var body: some Scene {
				// (other WindowGroup scenes)

        ImmersiveSpace(id: "solar-system") {
            SolarSystem()
        }
    }
}
Open ImmersiveSpace Action swift · at 21:25 ↗
@Environment(\.openImmersiveSpace)
private var openImmersiveSpace

Button("View Outer Space") {
    openImmersiveSpace(id: "solar-system")
}
ImmersionStyle swift · at 22:50 ↗
@main
struct WorldApp: App {
    @State private var selectedStyle: ImmersionStyle = .full
    var body: some Scene {
				// (other WindowGroup scenes)

        ImmersiveSpace(id: "solar-system") {
            SolarSystem()
        }
        .immersionStyle(selection: $selectedStyle, in: .full)
    }
}
Starfield swift · at 23:17 ↗
struct Starfield: View {
    var body: some View {
        RealityView { content in
            let starfield = await loadStarfield()
            content.add(starfield)
        }
    }
}
SolarSystem swift · at 23:28 ↗
struct SolarSystem: View {
    var body: some View {
        Earth()
        Sun()
      	Starfield()
    }
}

Resources