Build a responsive camera app that launches quickly
Build a fast camera launch experience for your iOS and iPadOS apps.
Overview
This sample demonstrates how to use the deferred start API and how to defer UI elements until after preview is running, to optimize a camera app for launch. The FastCameraLaunch sample builds off of AVCam. For more details on AVCam, see AVCam: Building a camera app.
Configure the sample code project
The sample app, FastCameraLaunch, requires the following:
Xcode 27.
An iOS device running iOS 27 or later.
FastCameraLaunch doesn’t work in Simulator, because Xcode can’t access the camera,
Postpone non-critical UI elements
The app’s UI plays an important role in the camera launch experience. When designing a launch flow, divide the app’s launch into two phases:
Resources critical for launching and displaying preview
Resources that can be created after preview is running
In FastCameraLaunch, there are several UI elements: a camera preview, a shutter button, an image well, and a mode picker. The camera preview is the most critical UI element for someone when they launch the app. The image well and the mode picker are not needed prior to preview rendering, so this work needs to wait until after preview has started.
Here’s an example of how to consider postponing elements until after launch:
@State var camera: CameraModel
var body: some View {
HStack {
if camera.status == .running {
ThumbnailButton(camera: camera)
// Hide the thumbnail button when a person interacts with capture controls.
.opacity(camera.prefersMinimizedUI ? 0 : 1)
.transition(.opacity.animation(.easeIn(duration: 0.3).delay(0.2)))
}
Spacer()
CaptureButton(camera: camera)
Spacer()
if camera.status == .running {
SwitchCameraButton(camera: camera)
// Hide the camera selection when a person interacts with capture controls.
.opacity(camera.prefersMinimizedUI ? 0 : 1)
.transition(.opacity.animation(.easeIn(duration: 0.3).delay(0.2)))
}
}
.foregroundColor(.white)
}Opt into deferred start
Initializing AVCaptureOutput objects is expensive, and significantly slows down launch. An app only needs one output initialized in order to render preview. Outputs such as AVCaptureMovieFileOutput and AVCapturePhotoOutput are not necessary for preview, while AVCaptureVideoPreviewLayer is essential. To reduce the time spent in AVCaptureOutput initialization, use the Deferred Start API.
Each AVCaptureOutput and AVCaptureVideoPreviewLayer object has an isDeferredStartEnabled property. Set this property to true to defer an output. To optimize for launch, defer all outputs except the output the app uses to render preview.
There are two ways the app can specify when to run the initializations: Automatic Start and Manual Start.
For apps which that recompile against the iOS 26.0 SDK, the default behavior is to run in automatic mode. The automaticallyRunsDeferredStart property is set to true when using automatic mode
// Deferred start.
captureSession.automaticallyRunsDeferredStart = true
photoCapture.output.isDeferredStartEnabled = true
captureSession.setDeferredStartDelegate(deferredStartDelegate, deferredStartDelegateCallbackQueue: sessionQueue)
// Commit the capture session configuration.
captureSession.commitConfiguration()If you want to fine-tune this control in your app, the Deferred Start API offers a manual start option with the runDeferredStartWhenNeeded property.
To opt in to this mode, set the automaticallyRunsDeferredStart property on AVCaptureSession to false.
Once an app finishes its start-up operations, such as non-critical resource creation, call the runDeferredStartWhenNeeded method on the AVCaptureSession to inform the system that now is an good time to run deferred-start initialization
See Also
Capture sessions
Setting up a capture sessionAccessing the camera while multitasking on iPadAVCam: Building a camera appCapturing Cinematic videoSupporting Center Stage front camera in your iOS appAVMultiCamPiP: Capturing from Multiple CamerasAVCamBarcode: detecting barcodes and facesAVCaptureSessionAVCaptureMultiCamSessionAVCaptureInputAVCaptureOutputAVCaptureConnection