iPhone Duo Fold & Pose Development Guide
Detect and respond to iPhone Duo fold state and pose changes, and keep content and controls clear of the hinge.
Last updated
Quick answer
Don't detect iPhone Duo's fold state or hinge angle to drive layout — read size class and geometry, and use ArrangementView plus ReservedRegion. Read hinge data with SwiftUI onHingeChange(isEnabled:_:) or UIKit UIHingeInteraction / UIHinge only for interactions and effects; a nil hinge means the device has no hinge. Reserve pose-specific code (closed, half-open, fully open) for genuinely pose-dependent behavior, like pausing playback.
Understanding poses
Apple refers to the physical configuration of iPhone Duo as its "pose." Your app can be running through any of these poses, and the system may transition between them while the app stays in the foreground.
Closed
Device is folded shut; outer display active.
Half-open
Partially unfolded, often used hands-free like a laptop.
Fully open
Flat, maximum available width across both halves.
Detecting fold state
Don't try to detect the fold state directly to make layout decisions — read the resulting size class and geometry changes instead. If you do need pose-specific behavior (for example, pausing playback when half-open), use the scene's environment values rather than a private or undocumented API.
Apple recommendation
Usually, you shouldn't detect the hardware pose at all. Detect available layout space, and let size classes and safe area insets drive your UI. Reserve pose-specific code for genuinely pose-dependent behavior, not layout.
Hinge angle
Use SwiftUI onHingeChange(isEnabled:_:) to receive a DeviceHingeContext, or UIKit UIHingeInteraction / UIHinge for the same data with the angle in radians. Hinge data is for interactions and effects — Apple's guitar pitch-bend demo is the model — not for layout.
- Need an interaction tied to fold motion (pitch bend, a visual effect) → read
hinge.angleandstatus. - Need to place content around the fold → ArrangementView and ReservedRegion, never frames from
hinge.angle. hingeis optional. ADeviceHingehasangleandstatus.closed|.partiallyOpen|.fullyOpen. UIKit status also includes.unknown. Nil hinge means no hinge (other iPhones).
ContentView()
.onHingeChange(isEnabled: true) { context in
guard let hinge = context.hinge else { return }
applyPitchBend(angle: hinge.angle, status: hinge.status)
}Common mistake
Don't drive layout from hinge angle. Computing frames from hinge.angle fights ArrangementView and ReservedRegion and breaks on devices with no hinge.
Avoiding the fold
Use ReservedRegion to keep custom controls clear of the hinge automatically, rather than hardcoding an inset that matches today's hardware:
VStack {
ContentView()
ControlBar()
}
.reservedRegion(.systemControls) { region in
ControlBar()
.padding(.bottom, region.insets.bottom)
}Animating transitions
Wrap layout changes that respond to size class or geometry updates in withAnimation so pose transitions read as a smooth resize rather than a layout jump. Keep animations short — under 300ms — so the UI feels responsive during a fold or unfold.
Frequently asked questions
What is a "pose" on iPhone Duo?
A pose is the physical configuration of the device — closed (folded shut, outer display active), half-open (used hands-free like a laptop), or fully open (flat, maximum available width). The system can move your app between poses while it stays in the foreground.
How do I detect the fold state?
Usually you shouldn't detect it directly. Read the resulting size class and geometry changes instead, and let those drive your layout. Reserve pose-specific detection for genuinely pose-dependent behavior, like pausing playback when the device goes half-open — not for layout decisions.
How do I read the hinge angle on iPhone Duo?
Use SwiftUI onHingeChange(isEnabled:_:) to receive a DeviceHingeContext, or UIKit UIHingeInteraction / UIHinge for the same data in radians. The hinge property is optional: a DeviceHinge has angle plus status .closed, .partiallyOpen, or .fullyOpen (UIKit also has .unknown); nil means the device has no hinge. Use that data for interactions and effects, not layout.
Should I lay out views from hinge.angle?
No. Layout uses ArrangementView and ReservedRegion — do not compute frames from hinge.angle. Hinge data is for interactions and effects (Apple’s guitar pitch-bend demo), not for deciding where UI sits.
How do I keep controls clear of the hinge?
Use SwiftUI's ReservedRegion API to keep custom controls clear of the fold automatically, instead of hardcoding an inset that matches only today's hardware.