LimitedRound 2 is open. Get your first month free, no extra charge.Join the waitlist ›
Wire in your backend

How to add camera access to a SwiftUI app

TL;DR. SwiftUI has no native camera view, so you wrap UIImagePickerController or AVFoundation in a UIViewControllerRepresentable. Capturing requires an NSCameraUsageDescription string in Info.plist, which App Review reads and the OS shows in the permission prompt. AppFlight adds the usage string and generates the wrapper.

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.

Sources

Build this app without opening Xcode.

AppFlight turns a plain-English prompt into a real native iOS app and ships it to the App Store. Round 2 is open: free for your first month.

Join the waitlist