How it works
ImmersionChangeContext describes the state of immersion at a single moment in a visionOS scene, exposing how much of the surrounding passthrough the system has replaced with your immersive content. SwiftUI hands you these values in pairs — the immersion as it was and as it now is — so you can observe transitions rather than poll a property. Reach for it inside an immersion-change handler when you need to react to the user dialing immersion up or down, for example to fade audio, swap a skybox, or adjust scene lighting as the world opens up around them.
Receive old and new contexts in onImmersionChange
The handler attached with
onImmersionChangefires whenever the immersion level moves, and SwiftUI passes two ImmersionChangeContext values into the closure: the state before the change and the state after it. In the example these arrive asoldContextandnewContext, giving you both ends of the transition in one call so you can compare them or compute a delta.Read the immersion through the amount property
ImmersionChangeContext surfaces the current depth of immersion as a normalized value you read from its
amountmember. The closure readsoldContext.amountandnewContext.amountto see where immersion started and where it ended up — each is a fraction of the way between no immersion and full immersion, the same scale the surroundingSliderdrives from0...1.Drive side effects from the transition
Because you hold both contexts at once, you can branch on the direction or magnitude of the change rather than just the latest value. Here the handler simply logs
"from \(oldContext.amount) to \(newContext.amount)", but the same pair is where you would trigger work that should happen as immersion rises or falls.Attach the observer where the scene lives
ImmersionChangeContext is delivered through a view modifier, so
onImmersionChangeplugs onto the view whose immersion you care about — in the example it sits on the paddedVStack. The symbol itself carries no initializer you call; you consume the contexts SwiftUI constructs for you when the level changes.
print body with if newContext.amount > oldContext.amount { print("deeper") } to watch ImmersionChangeContext distinguish increasing immersion from decreasing as you drag the Slider.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 ImmersionChangeContextDemo: View {
@State private var amount = 0.0
var body: some View {
VStack(spacing: 12) {
Text("Immersion: \(Int(amount * 100))%")
.font(.headline)
Slider(value: $amount, in: 0...1)
}
.padding()
.onImmersionChange { oldContext, newContext in
print("from \(oldContext.amount) to \(newContext.amount)")
}
}
}