Camera Access
Requesting Camera Permission
Before accessing the camera, you must request permission. Add NSCameraUsageDescription to your Info.plist with a clear description.
import AVFoundation
class CameraPermissionManager: ObservableObject {
@Published var hasPermission = false
func checkPermission() {
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
hasPermission = true
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { granted in
DispatchQueue.main.async { self.hasPermission = granted }
}
case .denied, .restricted:
hasPermission = false
@unknown default:
hasPermission = false
}
}
}
Setting Up AVCaptureSession
AVCaptureSession manages the flow of data from camera input to output.
import AVFoundation
import UIKit
class CameraManager: NSObject, ObservableObject {
var captureSession: AVCaptureSession?
var photoOutput: AVCapturePhotoOutput?
var previewLayer: AVCaptureVideoPreviewLayer?
@Published var lastPhoto: UIImage?
func setupCamera() {
captureSession = AVCaptureSession()
captureSession?.sessionPreset = .photo
guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back),
let input = try? AVCaptureDeviceInput(device: camera) else { return }
if captureSession?.canAddInput(input) == true {
captureSession?.addInput(input)
}
photoOutput = AVCapturePhotoOutput()
if captureSession?.canAddOutput(photoOutput!) == true {
captureSession?.addOutput(photoOutput!)
}
captureSession?.startRunning()
}
}
Camera Device Configuration
Configure camera properties like focus, exposure, and white balance.
func configureCamera() throws {
guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
throw CameraError.deviceNotFound
}
try camera.lockForConfiguration()
// Auto focus
if camera.isFocusModeSupported(.continuousAutoFocus) {
camera.focusMode = .continuousAutoFocus
}
// Auto exposure
if camera.isExposureModeSupported(.continuousAutoExposure) {
camera.exposureMode = .continuousAutoExposure
}
// Auto white balance
if camera.isWhiteBalanceModeSupported(.continuousAutoWhiteBalance) {
camera.whiteBalanceMode = .continuousAutoWhiteBalance
}
camera.unlockForConfiguration()
}
Photo Capture
Capturing Photos
Use AVCapturePhotoOutput to capture photos from the camera session.
extension CameraManager: AVCapturePhotoCaptureDelegate {
func capturePhoto() {
let settings = AVCapturePhotoSettings()
settings.flashMode = .auto
settings.isHighResolutionPhotoEnabled = true
photoOutput?.capturePhoto(with: settings, delegate: self)
}
func photoOutput(_ output: AVCapturePhotoOutput,
didFinishProcessingPhoto photo: AVCapturePhoto,
error: Error?) {
guard let data = photo.fileDataRepresentation(),
let image = UIImage(data: data) else { return }
DispatchQueue.main.async {
self.lastPhoto = image
}
}
}
SwiftUI Camera Interface
Build a custom camera view using UIViewRepresentable.
struct CameraPreviewView: UIViewRepresentable {
let session: AVCaptureSession
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: UIScreen.main.bounds)
let previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.frame = view.bounds
previewLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(previewLayer)
return view
}
func updateUIView(_ uiView: UIView, context: Context) { }
}
struct CameraScreen: View {
@StateObject private var camera = CameraManager()
var body: some View {
ZStack {
if let session = camera.captureSession {
CameraPreviewView(session: session)
.ignoresSafeArea()
}
VStack {
Spacer()
Button(action: { camera.capturePhoto() }) {
Circle()
.fill(.white)
.frame(width: 80, height: 80)
.overlay(Circle().stroke(.gray, lineWidth: 4))
}.padding(.bottom, 30)
}
}
.onAppear { camera.setupCamera() }
}
}
Photos Library Integration
PHPickerViewController
Use the modern PHPickerViewController to let users select photos from their library.
import SwiftUI
import PhotosUI
struct PhotoPickerView: UIViewControllerRepresentable {
@Binding var selectedImages: [UIImage]
let selectionLimit: Int
@Environment(\.dismiss) var dismiss
func makeUIViewController(context: Context) -> PHPickerViewController {
var config = PHPickerConfiguration()
config.selectionLimit = selectionLimit
config.filter = .images
let picker = PHPickerViewController(configuration: config)
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) { }
func makeCoordinator() -> Coordinator { Coordinator(self) }
class Coordinator: NSObject, PHPickerViewControllerDelegate {
let parent: PhotoPickerView
init(_ parent: PhotoPickerView) { self.parent = parent }
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
let group = DispatchGroup()
var images: [UIImage] = []
for result in results {
group.enter()
result.itemProvider.loadObject(ofClass: UIImage.self) { image, _ in
if let image = image as? UIImage { images.append(image) }
group.leave()
}
}
group.notify(queue: .main) {
self.parent.selectedImages = images
self.parent.dismiss()
}
}
}
}
Saving to Photos Library
Save captured images to the user's photo library using PHPhotoLibrary.
import Photos
func saveToPhotosLibrary(image: UIImage) {
PHPhotoLibrary.shared().performChanges {
PHAssetChangeRequest.creationRequestForAsset(from: image)
} completion: { success, error in
if success {
print("Photo saved successfully")
} else if let error = error {
print("Failed to save: \(error.localizedDescription)")
}
}
}
Fetching Photos from Library
Access photos programmatically using PHAsset and PHImageManager.
import Photos
func fetchRecentPhotos(limit: Int = 10) -> [UIImage] {
var images: [UIImage] = []
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchOptions.fetchLimit = limit
let assets = PHAsset.fetchAssets(with: .image, options: fetchOptions)
let imageManager = PHImageManager.default()
assets.enumerateObjects { asset, _, _ in
let options = PHImageRequestOptions()
options.synchronous = true
options.deliveryMode = .highQualityFormat
imageManager.requestImage(
for: asset,
targetSize: CGSize(width: 200, height: 200),
contentMode: .aspectFill,
options: options
) { image, _ in
if let image = image { images.append(image) }
}
}
return images
}
Quiz
1. What Info.plist key is required for camera access?
2. What class manages the camera session flow?
3. How do you capture a photo with AVCaptureSession?
4. What is PHPickerViewController used for?
Flashcards
Question
What permission is needed for camera access?
Click to reveal answer
Answer
Add NSCameraUsageDescription to Info.plist and request AVCaptureDevice.requestAccess(for: .video).
Question
How does AVCaptureSession work?
Click to reveal answer
Answer
It connects AVCaptureDeviceInput (camera) to AVCaptureOutput (photo/video) and manages the data flow.
Question
What is the modern way to pick photos in iOS?
Click to reveal answer
Answer
PHPickerViewController provides a system photo picker with configurable filters and selection limits.
Question
How do you save an image to the photo library?
Click to reveal answer
Answer
Use PHPhotoLibrary.shared().performChanges with PHAssetChangeRequest.creationRequestForAsset(from:).
Revision Notes
Key Takeaways
- 1. Request camera permission before accessing AVCaptureSession
- 2. AVCaptureSession connects camera input to output
- 3. Use AVCapturePhotoOutput to capture still images
- 4. PHPickerViewController is the modern photo picker
- 5. PHPhotoLibrary handles saving and fetching photos
Interview Tips
- • Explain the AVCaptureSession pipeline: input -> session -> output
- • Discuss how to handle camera permission denial gracefully
- • Describe the difference between synchronous and asynchronous image loading
Cheat Sheet
Camera & Photos Quick Reference
- NSCameraUsageDescription - Required Info.plist key
- AVCaptureSession - Manages camera data flow
- AVCapturePhotoOutput - Captures photos
- AVCapturePhotoCaptureDelegate - Handles captured photos
- PHPickerViewController - System photo picker
- PHPhotoLibrary - Save and fetch photos
- PHAsset - Represents a photo/video asset
- PHImageManager - Load image data from assets