The Deferred Start API allows camera apps to postpone initialization of non-essential AVCaptureOutputs until after the first preview frame appears, dramatically reducing launch latency. Introduced in iOS 26, this API can cut camera app launch time in half by decoupling preview readiness from full output initialization.
โข Camera launch time can be cut by ~2x โ outputs like AVCapturePhotoOutput and AVCaptureMovieFileOutput are deferred until after preview is already rendering
โข Two modes available: automatic (system picks the best time post-preview) and manual (app controls exactly when deferred init runs, useful when using AVCaptureVideoDataOutput for custom preview rendering)
โข Combine with isResponsiveCaptureEnabled on AVCapturePhotoOutput so users can trigger a capture immediately even before the photo output finishes its deferred initialization
Demonstrates configuring an AVCaptureSession with Deferred Start so that only the preview layer initializes at launch, while the photo output is deferred until after the first frame renders โ halving typical launch time.
import AVFoundation
import UIKit
class CameraViewController: UIViewController {
private let session = AVCaptureSession()
private let photoOutput = AVCapturePhotoOutput()
private let previewLayer = AVCaptureVideoPreviewLayer()
private let sessionQueue = DispatchQueue(label: "com.example.camera.session")
override func viewDidLoad() {
super.viewDidLoad()
setupPreviewLayer()
// Configure session off the main thread to avoid blocking UI
sessionQueue.async { self.configureSession() }
}
private func setupPreviewLayer() {
previewLayer.videoGravity = .resizeAspectFill
previewLayer.frame = view.bounds
view.layer.insertSublayer(previewLayer, at: 0)
}
private func configureSession() {
guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera,
for: .video,
position: .back),
let input = try? AVCaptureDeviceInput(device: camera) else { return }
session.beginConfiguration()
session.sessionPreset = .photo
// Enable automatic deferred start โ system will defer after first preview frame
session.automaticallyRunsDeferredStart = true
if session.canAddInput(input) {
session.addInput(input)
}
// Preview layer is NOT deferred โ it must be ready immediately
previewLayer.session = session
// isDeferredStartEnabled defaults to false, so preview layer initializes eagerly
// Photo output IS deferred โ not needed until user taps shutter
if session.canAddOutput(photoOutput) {
session.addOutput(photoOutput)
photoOutput.isDeferredStartEnabled = true
// Allow capture requests even before deferred init completes
photoOutput.isResponsiveCaptureEnabled = true
}
session.commitConfiguration()
// Set delegate to receive deferred-start lifecycle callbacks
session.deferredStartDelegate = self
session.startRunning()
}
@IBAction func shutterTapped(_ sender: UIButton) {
let settings = AVCapturePhotoSettings()
photoOutput.capturePhoto(with: settings, delegate: self)
}
}
extension CameraViewController: AVCaptureSessionDeferredStartDelegate {
func captureSessionWillRunDeferredStart(_ session: AVCaptureSession) {
// Good moment to prepare any non-critical background resources
print("Deferred start beginning โ photo output about to initialize")
}
func captureSessionDidRunDeferredStart(_ session: AVCaptureSession) {
// All deferred outputs are now fully initialized
DispatchQueue.main.async {
// Fade in non-critical UI elements now that full session is ready
print("Deferred start complete โ all outputs ready")
}
}
}
extension CameraViewController: AVCapturePhotoCaptureDelegate {
func photoOutput(_ output: AVCapturePhotoOutput,
didFinishProcessingPhoto photo: AVCapturePhoto,
error: Error?) {
guard error == nil, let data = photo.fileDataRepresentation() else { return }
print("Captured photo: \(data.count) bytes")
}
}Deferring AVCapturePhotoOutput means the first capture request may be delayed while the output finishes initialization; mitigate this by also setting isResponsiveCaptureEnabled = true. In manual mode you must call runDeferredStartWhenNeeded() yourself โ forgetting to call it means deferred outputs never initialize. Apps recompiled against iOS 26+ SDK have automaticallyRunsDeferredStart set to true by default.
Requires devices running iOS 26 or later. Benefits scale with session complexity โ apps with many outputs see larger improvements.
More iOS 27 APIs land every week.
Get notified when new capabilities are published โ no noise, just signal.