Build a Great Camera Experience for iPhone Duo
Source: Build a great camera experience for iPhone Duo (Apple Developer) · 9 min 28s
By Tarun (Camera Software team).
iPhone Duo has two front cameras — a fact that breaks the "front = facing you" assumption and needs a plan. This session covers the new cameras, how to handle direction changes as people open/close the device, and how to polish your preview.
Two front cameras
Both are square sensors with an ultrawide field of view:
- Outer ultrawide (on the outside of the device): up to 4K @ 120fps.
- Inner ultrawide (the first under-display camera on iPhone): 1080p @ 60fps.
Your app streams from them through AVFoundation, same as always — request .front + Wide/UltraWide device type via AVCaptureDeviceDiscoverySession.
The Virtual Front Camera does the heavy lifting
When you discover the .front camera on Duo, you get a new Virtual Front Camera: a device that automatically switches between the outer and inner physical cameras so you're always streaming from the most relevant one (inner when open, outer when closed). You don't have to do anything.
Trade-off: the virtual camera only exposes features common to both — max 1080p @ 60fps, and no depth. If you need the full capabilities, use the individual device types (builtInOuterUltraWideCamera, builtInInnerUltraWideCamera) — but then you must handle the switching when the device opens/closes.
Direction: cameras don't always face you anymore
Here's the twist: with two displays that can face opposite ways, a "front" camera isn't always looking at you. Example: you read the inner display while streaming from the outer front camera — that camera is now facing away. Then if you close the device, that same camera swings around to face you.
So AVCaptureDevice.position == .front is no longer a guarantee it's forward-facing. Solve it with the new AVCaptureDeviceDirectionCoordinator (in AVKit):
- Create one per UI view: pass your UIView, the device types to monitor, and a change handler.
- Each coordinator reports facing relative to its own view. On the outer display, the outer front camera is forward-facing; if your view moves to the inner display, the coordinator tells you the inner front camera is now forward-facing.
- With two views (one per display), create a coordinator for each.
```swift
// The change handler tells you which camera is now forward-facing
coordinator.onFacingChange = { facing in
// reconfigure your AVCaptureSession to stream from the forward-facing camera
// re-decide preview mirroring (mirror for a natural selfie)
// do any UI updates for the camera switch
}
```
Two implementation notes:
- The coordinator gives you an
AVCaptureDeviceDescriptor(a main-actor-safe, sendable stand-in), not anAVCaptureDevice. Pass the descriptor to your camera actor and build the device there — the change handler shouldn't hit AVFoundation APIs directly. - Decide mirroring based on the new direction: mirror the preview when the rear camera is forward-facing for a natural selfie.
Polish the preview
- Wide screen, square sensor: when streaming the full field of view on the inner display you get extra space around the preview — offset it to group controls there, or fill the display; your call, via
videoGravityonAVCaptureVideoPreviewLayer. - Fill the display: use the square sensor +
dynamicAspectRatioto pick a landscape ratio on the inner display. - Rotation: adopt the existing
AVCaptureDeviceRotationCoordinator— it now updates when your app moves displays, so previews/photos stay upright. After adopting it, disable camera-sensor-orientation compensation to improve performance.
Next steps
- Build with the iOS 27.1 SDK.
- Decide switching strategy: use the Virtual Front Camera (zero work, capped 1080p/60) or individual cameras + a direction coordinator (full capability, you manage the switch).
- Test the preview in every pose on the real device/simulator.
→ Two-display camera UI (CameraCaptureAccessory) is covered in "Leverage multiple displays and scenes on iPhone Duo."