Leverage multiple displays and scenes on iPhone Duo
Build iPhone Duo experiences that respond to hinge angle, support side-by-side multitasking and multiple scenes, and span displays with scene accessories.
TL;DR
- Use SwiftUI's
onHingeChangeor UIKit'sUIHingeInteractionto observe hinge status and continuous angle updates for live interactions and effects. - Treat hinge data as an interaction signal, not a layout mechanism; use arrangement, region, size class, and scene geometry APIs for layout decisions.
- All apps participate in iPhone Duo multitasking, and iPhone Duo supports multiple instances of an app's UI, with new-window creation dynamically unavailable on the outer display.
- Use scene accessories, including
CameraCaptureAccessory, to pair supplementary UI with a main scene across displays and observe accessory availability changes.
Respond to the hinge
iPhone Duo exposes hinge information so apps can react to the device being closed, partially open, or fully open. SwiftUI uses the onHingeChange modifier, while UIKit uses UIHingeInteraction. Both provide high-level status and continuous hinge angle updates.
The session's example uses the hinge angle to drive a guitar pitch bend. The implementation keeps the effect in view state, checks that a hinge exists, limits the effect to the partially open state, and resets the state when hinge data should not be used.
- A
nilhinge means the app is running on a device without a hinge. - Use
hinge.status == .partiallyOpenwhen an interaction only makes sense while the device is being flexed. - Reset interaction state when the hinge is unavailable or not in the expected state.
Drive an effect from hinge angle in SwiftUI
Observe the current hinge context, guard for hinge availability and state, then map hinge.angle into app-specific state.
struct InstrumentView: View {
/// Normalized bend, 0 is no bend, 1 is deepest bend
@State private var pitchBend: Double = 0
var body: some View {
GuitarView(pitchBend: pitchBend)
.onHingeChange { _, context in
if let hinge = context.hinge, hinge.status == .partiallyOpen {
pitchBend = calculatePitchBend(angle: hinge.angle)
}
else {
pitchBend = 0
}
}
}
private func calculatePitchBend(angle: Angle) -> Double { ... }
}Use layout APIs for layout, not hinge angle
Hinge observations are live input suitable for effects, gestures, and other interactive behavior. Layout should instead be driven by the platform's adaptive layout APIs.
For iPhone Duo layouts, use arrangement and region APIs, along with familiar tools such as size classes and scene geometry. The related session "Strike a pose with adaptive layouts on iPhone Duo" covers those APIs in more detail.
- Use hinge angle for continuous effects such as zooms, bends, or other direct feedback.
- Use arrangement and region APIs when deciding where UI belongs around the fold or across displays.
- Use size classes and scene geometry for multitasking and dynamically resized windows.
Prepare for split view multitasking and multiple scenes
All apps participate in multitasking on iPhone Duo, where two apps can be placed side by side. iPhone Duo also introduces a layout that stacks video and apps together; apps should handle these layouts through the same adaptive layout techniques.
iPhone Duo is the first iPhone to support multiple instances of an app's UI. Apps that already support multiple windows on iPad also support this on iPhone Duo, but there is a platform-specific constraint: new windows cannot be created on the outer display. New window creation is reserved for the inner display.
- If the app already resizes well on iPad or iPhone mirroring, it has a strong starting point for iPhone Duo multitasking.
- Handle errors when requesting new scenes because availability can change dynamically.
- Use the
UIWindowSceneActivationaction for user-facing new-window UI; it automatically hides when new windows are unavailable. - Consult multiple-scene documentation if adding multiwindow support for the first time.
Span displays with scene accessories
Scene accessories let an app pair supplementary content with its main UI on another display. The session frames this as a way to show app-controlled companion UI across displays, such as using one device display as a controller or showing supporting content while the main scene remains elsewhere.
Accessory availability is controlled by the system. Accessories are enabled by default, can be toggled, and may become unavailable as conditions change. Apps should observe availability so controls and state stay synchronized.
- Register accessories where they are relevant in the view hierarchy so the accessory appears only while that UI is visible.
- Use an enabled binding when the user should be able to toggle the accessory.
- Use
onAvailabilityChangeto update app state when the accessory can no longer be shown.
Register a camera capture accessory
Attach the accessory to the camera UI so the teleprompter appears on the outer display only while the camera view is visible.
struct CameraRootView: View {
@State private var model = TeleprompterModel()
var body: some View {
CameraView(model: model)
.sceneAccessory {
CameraCaptureAccessory {
TeleprompterView(model: model)
}
}
}
}Toggle the accessory and react to availability
Bind accessory enablement to model state and disable the toolbar toggle when the system reports the accessory is unavailable.
struct CameraRootView: View {
@State private var model = TeleprompterModel()
var body: some View {
CameraView(model: model)
.sceneAccessory {
CameraCaptureAccessory(isEnabled: $model.isEnabled) {
TeleprompterView(model: model)
}
.onAvailabilityChange { newValue in
model.isAvailable = newValue
}
}
.toolbar {
TeleprompterToggle(isEnabled: $model.isEnabled)
.disabled(!model.isAvailable)
}
}
}CameraCaptureAccessory for camera apps
CameraCaptureAccessory is a scene accessory for camera apps on iPhone Duo. It lets the app keep its main camera UI on the inner display while showing additional UI on the outer display, such as a teleprompter for the person being recorded.
The accessory is available when the app is full screen on the inner display and has an active camera session. Register it on the same view as the camera UI.
- Use it for camera-related supplementary UI shown to the subject while capturing photo or video.
- Expect availability to change, for example when the device is closed.
- For deeper camera-specific behavior, consult the related session "Build a great camera experience for iPhone Duo".
Related Sessions
Prepare your app for iPhone Duo
Update iPhone apps for iPhone Duo's foldable displays with Xcode 27.1, adaptive layouts, size classes, safe areas, and reserved regions.
Raise the bar with iPhone Duo
Adapt SwiftUI and UIKit navigation, toolbar, and tab bar layouts for iPhone Duo's vertical shared bar region, overflow, and custom item behavior.