iPhone Duo is the first iPhone with two front cameras. Both are square sensors with an ultrawide field of view, but they are not the same camera. Through AVFoundation, the outer ultrawide camera supports up to 4K at 120fps, and the inner ultrawide camera, the first under-display camera on iPhone, supports 1080p at up to 60fps. Plan for a capability change, not just a viewpoint change, when the device opens.
Apple’s consumer specifications describe the same outer camera as a 12MP Center Stage camera that records 4K Dolby Vision to 60fps. That is what the built-in Camera app records; the figures above are what Apple’s camera Tech Talk gives developers streaming through AVFoundation.
Decide first: virtual or individual
Virtual front camera — a new AVCaptureDevice that switches between the inner and outer cameras automatically as the device opens and closes. You discover it with the usual front-camera query. It only offers what both cameras have in common, which means at most 1080p at 60fps, and no depth. For most apps that is the simplest correct answer.
AVCaptureDeviceDiscoverySession(
deviceTypes: [.builtInWideCamera, .builtInUltraWideCamera],
mediaType: .video,
position: .front
)
Individual cameras — each front camera has its own device type, giving access to its full capabilities, including depth, which is only available this way:
.builtInOuterUltraWideCamera // front camera on the outer display
.builtInInnerUltraWideCamera // front camera on the inner display
Apple’s direction coordinator example also monitors a rear camera, .builtInDualWideCamera, because on iPhone Duo the rear cameras can face the user too.
If you choose individual cameras, you take on responsibility for switching when the device opens or closes, and you need the direction coordinator.
The direction coordinator
directionCoordinator = AVCaptureDeviceDirectionCoordinator(
view: view,
deviceTypes: [
.builtInOuterUltraWideCamera,
.builtInInnerUltraWideCamera,
.builtInDualWideCamera,
],
changeHandler: { [weak self] map in
self?.updateCameraSession(map)
}
)
It lives in AVKit and, because it is tied to a view, is main-actor isolated. The camera position property has always said only front or back, and on iPhone Duo a front camera is not always facing the user. The coordinator reports which cameras face toward and away from the view, and calls your handler as that changes.
Apple is specific about the change handler: do not call AVFoundation APIs from it directly. It hands you an AVCaptureDeviceDescriptor, a sendable, main-actor-safe description of the device, which you pass to your camera actor. In the handler, reconfigure the session to keep streaming from the forward-facing camera, decide whether to mirror the preview, and update your UI.
Multiple displays
A camera app can use both displays at once, for example to show a child something fun on the outer display while you take their photo. That gives you one view per display, so create a separate direction coordinator for each view. Each reports directions relative to its own view: the same rear cameras are forward-facing for the outer display’s coordinator and backward-facing for the inner one’s. Show UI on the second display with the scene accessories API.
How to verify
Start capture, then fold and unfold the device repeatedly while watching the preview. It should follow the active display without dropping frames or stalling, and the correct lens should be selected in each state.