How to add camera access to a SwiftUI app
What camera access does for an iOS app
Camera access lets an app capture a photo or video in the moment, for a profile picture, a document scan, a receipt, or an image to send to an AI model. Unlike the photo picker, capture touches a sensitive sensor, so the OS gates it behind an explicit permission the user must grant, and that permission stays revocable in Settings. Your job is to explain the use clearly, handle the denied case without breaking the flow, and only ask when the feature actually needs it. For choosing existing photos, the picker is the lighter, permission-free option.
Adding camera access with AppFlight
Camera capture needs the NSCameraUsageDescription string in Info.plist, and the wrapper that bridges UIKit into SwiftUI. In AppFlight you describe the feature, like taking a photo for a post, and the AI generates a UIViewControllerRepresentable around UIImagePickerController plus the state to present it in a sheet. AppFlight adds the usage string, which App Review reads, and you make sure it describes the real feature. There is no key involved, so nothing is classified as client or backend.
A SwiftUI example
Wrap UIImagePickerController and present it from a SwiftUI view:
import SwiftUI
import UIKit
struct CameraPicker: UIViewControllerRepresentable {
var onCapture: (UIImage) -> Void
func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = .camera
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ controller: UIImagePickerController, context: Context) {}
func makeCoordinator() -> Coordinator { Coordinator(onCapture: onCapture) }
final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let onCapture: (UIImage) -> Void
init(onCapture: @escaping (UIImage) -> Void) { self.onCapture = onCapture }
func imagePickerController(
_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]
) {
if let image = info[.originalImage] as? UIImage { onCapture(image) }
picker.dismiss(animated: true)
}
}
}
Present it with .sheet(isPresented:), and add the NSCameraUsageDescription key to Info.plist so the permission prompt has a reason and the app does not crash.
Alternatives
For full control over a live capture screen, custom overlays, or barcode and document scanning, you build with AVFoundation using AVCaptureSession, at the cost of more code. VisionKit offers ready-made document and data scanners on top of the camera if that is your use case. When the user only needs to pick an existing image, PhotosPicker avoids the permission entirely and is the better default.
FAQ
Does SwiftUI have a built-in camera view?
Not for capture. PhotosPicker covers picking existing photos, but to take a new photo you wrap UIImagePickerController with sourceType .camera, or build a custom capture screen with AVFoundation, inside a UIViewControllerRepresentable.
What does the camera permission need?
An NSCameraUsageDescription string in Info.plist that explains why the app uses the camera. Without it the app crashes the first time it accesses the camera, and App Review checks that the wording matches the actual feature. The user grants or denies the prompt.
Camera or photo picker?
Use PhotosPicker when the user should choose an existing photo, since it needs no permission. Use the camera wrapper when the feature genuinely requires capturing something live, like scanning a receipt or taking a profile photo on the spot.