How it works
ImmersiveSpaceContent is the protocol that describes what your app presents inside an immersive space on visionOS — the unbounded scene that surrounds the wearer rather than living in a flat window. You adopt it to declare the entities, layers, and effects that fill the space, and SwiftUI hosts that content when the space opens. Reach for ImmersiveSpaceContent whenever a window or volume isn't enough and you need the system to step aside so your content can occupy the surrounding environment.
Conform a content type to ImmersiveSpaceContent
A type that conforms to ImmersiveSpaceContent supplies a
bodydescribing the immersive scene, much as aViewdescribes a window's contents. It is the payload anImmersiveSpacescene presents — the demo'sImmersiveSpaceContentDemoplays the controlling-view role here, deciding whether that payload should be on screen.Drive presentation from app state
Because an immersive space is opened and dismissed rather than always shown, you gate it on observable state. The example tracks this with
@State private var spaceOpen, and ImmersiveSpaceContent is only hosted while that flag indicates the space should be active.Open and dismiss the space from a control
Presentation is a request, not a direct mount: a control asks the system to open or close the space. The
ButtontogglingspaceOpenstands in for that request, flipping between"Open Space"and"Dismiss Space"to start or tear down the ImmersiveSpaceContent.Reflect the space's lifecycle back in the UI
Knowing whether the immersive space is currently presented lets the rest of your interface stay in sync. Here
Text(spaceOpen ? "Immersive Space Open" : "Immersive Space Closed")mirrors the ImmersiveSpaceContent's open or dismissed state so the wearer always sees its status.
@State private var spaceOpen = true so the ImmersiveSpaceContent is presented from launch, and watch the label and button label initialize to their open state.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct ImmersiveSpaceContentDemo: View {
@State private var spaceOpen = false
var body: some View {
VStack(spacing: 12) {
Image(systemName: "visionpro")
.font(.system(size: 44))
.foregroundStyle(.indigo)
Text(spaceOpen ? "Immersive Space Open" : "Immersive Space Closed")
.font(.headline)
Button(spaceOpen ? "Dismiss Space" : "Open Space") {
spaceOpen.toggle()
}
.buttonStyle(.borderedProminent)
}
.padding()
}
}