Skip to main content

Working with Camera and Photos

1. Using UIImagePickerController

Property Value Description
sourceType UIImagePickerController.SourceType Specifies the source of the media, such as camera or photo library.
allowsEditing Bool Enables or disables the editing mode for captured media.
mediaTypes UIImagePickerController.MediaType Defines the types of media that can be selected (e.g., photos, videos).
cameraDevice UIImagePickerController.CameraDevice Specifies which camera to use (front or rear).
cameraFlashMode UIImagePickerController.CameraFlashMode Sets the flash mode for camera capture (auto, on, off).

Example: Presenting UIImagePickerController

import UIKit

class ViewController: UIViewController {
    let imagePicker = UIImagePickerController()

    override func viewDidLoad() {
        super.viewDidLoad()
        imagePicker.delegate = self
        imagePicker.sourceType = .camera
        imagePicker.allowsEditing = true
    }

    @IBAction func openCamera(_ sender: UIButton) {
        present(imagePicker, animated: true)
    }
}

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let pickedImage = info[.editedImage] as? UIImage {
            // Use the picked image
        }
        dismiss(animated: true)
    }
}
Note: Ensure that you have added the appropriate permissions in your Info.plist file for camera access, such as NSCameraUsageDescription.

2. Accessing Camera

Property Value Description
AVCaptureDevice AVCaptureDevice Class for representing camera hardware
AVCaptureDevice.DiscoverySession AVCaptureDevice.DiscoverySession Discover available camera devices
AVCaptureDevice.Position .back, .front, .external Camera position options

Example: Request Camera Permission

import AVFoundation

func requestCameraPermission() {
    AVCaptureDevice.requestAccess(for: .video) { granted in
        if granted {
            print("Camera access granted")
        } else {
            print("Camera access denied")
        }
    }
}

Example: List Available Cameras

import AVFoundation

let discoverySession = AVCaptureDevice.DiscoverySession(
    deviceTypes: [.builtInWideAngleCamera],
    mediaType: .video,
    position: .unspecified
)

for device in discoverySession.devices {
    print("Device name: \(device.localizedName)")
    print("Position: \(device.position)")
}

3. Accessing Photo Library

Property Description Notes
PHPhotoLibrary.authorizationStatus() Returns the current authorization status for accessing the photo library Must be called on the main thread
PHPhotoLibrary.requestAuthorization() Requests permission to access the photo library Must be called on the main thread
PHAsset.fetchAssets() Fetches assets (photos/videos) from the library Supports filtering by media type, date range, etc.

Example: Requesting Photo Library Permission

import Photos

PHPhotoLibrary.requestAuthorization(.readWrite) { status in
    switch status {
    case .authorized:
        print("Access granted")
    case .denied, .restricted:
        print("Access denied")
    default:
        print("Not determined")
    }
}

Example: Fetching Photos

import Photos

let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]

let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)

for i in 0..<fetchResult.count {
    let asset = fetchResult.object(at: i)
    print("Asset ID: \(asset.localIdentifier)")
}
Note: Ensure NSPhotoLibraryUsageDescription is added to your app's Info.plist for permission request to work.

4. Using AVCaptureSession for Custom Camera

Example: Setting up AVCaptureSession

import AVFoundation

class CameraViewController: UIViewController {
    let captureSession = AVCaptureSession()
    var previewLayer: AVCaptureVideoPreviewLayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupCamera()
    }

    func setupCamera() {
        guard let videoDevice = AVCaptureDevice.default(for: .video) else { return }
        guard let videoInput = try? AVCaptureDeviceInput(device: videoDevice) else { return }

        captureSession.addInput(videoInput)
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer?.videoGravity = .resizeAspectFill
        view.layer.addSublayer(previewLayer!)
        
        captureSession.startRunning()
    }
}
Property Value Description
AVCaptureSession AVCaptureSession() Manages the flow of data from input to output
AVCaptureDeviceInput AVCaptureDeviceInput(device: device) Represents a camera or microphone input
AVCaptureVideoPreviewLayer AVCaptureVideoPreviewLayer(session: session) Displays live video preview from the capture session
Note: Ensure you have appropriate permissions in Info.plist for camera access.
Warning: Always check device availability before creating inputs.

Key Steps

  • Initialize AVCaptureSession
  • Create and add an input (e.g., camera)
  • Set up preview layer to display video feed
  • Start the session to begin capturing

5. Capturing Photos with AVCapturePhotoOutput

Property Value Description
photoOutput AVCapturePhotoOutput Instance of the photo output class for capturing photos
photoSettings AVCapturePhotoSettings Configuration object for photo capture settings
photoCaptureDelegate AVCapturePhotoCaptureDelegate Delegate to handle captured photo data

Example: Setting up photo capture

import AVFoundation

class PhotoCaptureManager: NSObject, AVCapturePhotoCaptureDelegate {
    let photoOutput = AVCapturePhotoOutput()
    
    func setupPhotoCapture() {
        guard let photoOutput = photoOutput else { return }
        // Configure session with photo output
        session.addOutput(photoOutput)
    }
    
    func capturePhoto() {
        let photoSettings = AVCapturePhotoSettings()
        photoOutput.capturePhoto(with: photoSettings, delegate: self)
    }
    
    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        // Handle captured photo
    }
}
Note: Ensure camera permissions are requested and granted before capturing photos.
Warning: Photo capture requires proper session configuration and delegate setup to avoid runtime crashes.
Setting Value Description
isHighResolutionPhotoEnabled Bool Enables high-resolution photo capture (default: false)
flashMode AVCaptureFlashMode Controls flash behavior (auto, on, off)
hdrEnabled Bool Enables High Dynamic Range (HDR) capture

6. Recording Videos with AVCaptureMovieFileOutput

Example: Recording Video

import AVFoundation
import UIKit

class VideoRecorderViewController: UIViewController {
    var captureSession: AVCaptureSession!
    var movieFileOutput: AVCaptureMovieFileOutput!
    var previewLayer: AVCaptureVideoPreviewLayer!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupCamera()
    }

    func setupCamera() {
        captureSession = AVCaptureSession()
        captureSession.sessionPreset = .medium

        guard let backCamera = AVCaptureDevice.default(for: .video) else { return }
        let input = try! AVCaptureDeviceInput(device: backCamera)
        captureSession.addInput(input)

        movieFileOutput = AVCaptureMovieFileOutput()
        captureSession.addOutput(movieFileOutput)

        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer.videoGravity = .resizeAspectFill
        view.layer.addSublayer(previewLayer)

        captureSession.startRunning()
    }

    @IBAction func recordButtonTapped() {
        let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("output.mov")
        movieFileOutput.startRecording(to: outputURL, recordingDelegate: self)
    }

    @IBAction func stopButtonTapped() {
        movieFileOutput.stopRecording()
    }
}

extension VideoRecorderViewController: AVCaptureFileOutputRecordingDelegate {
    func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingAt startTime: Date) {
        print("Started recording")
    }

    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingAt: Date) {
        print("Finished recording")
    }
}
Property Value Description
movieFileOutput AVCaptureMovieFileOutput Outputs recorded video to a file
startRecording(to:recordingDelegate:) Void Begins recording to a file URL
stopRecording() Void Stops recording and finalizes the file
Note: Ensure camera permissions are requested in Info.plist with NSCameraUsageDescription.
Warning: Video recording may consume significant storage and battery. Handle interruptions gracefully.

Key Points

  • AVCaptureMovieFileOutput is used to record video to a file.
  • Use startRecording(to:recordingDelegate:) to begin recording.
  • Call stopRecording() to finalize the file and notify delegate.
  • Permissions must be requested for camera access.

7. Implementing Camera Permissions

Permission Key Description Status
NSCameraUsageDescription NSCameraUsageDescription Explains why the app needs camera access NEW

Example: Requesting Camera Permission

import AVFoundation

func requestCameraPermission() {
    AVCaptureDevice.requestAccess(for: .video) { granted in
        if granted {
            // Camera access granted
        } else {
            // Handle denied permission
        }
    }
}
Note: The app must include the NSCameraUsageDescription key in Info.plist with a user-facing description.

8. Using PHPhotoLibrary for Photo Access

Example: Requesting Photo Library Permissions

import Photos

func requestPhotoLibraryPermission() {
    PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
        switch status {
        case .authorized:
            print("Photo library access granted")
        case .denied, .restricted:
            print("Photo library access denied")
        default:
            print("Permission not determined")
        }
    }
}
Permission Type Description Notes
PHAuthorizationStatus.notDetermined User has not yet made a choice Must request permission before accessing library
PHAuthorizationStatus.authorized User has granted access Can read and write to library
PHAuthorizationStatus.denied User has denied access Access is permanently restricted
PHAuthorizationStatus.restricted Access is restricted (e.g., parental controls) May still access some photos
Note: You must add NSPhotoLibraryUsageDescription to your app's Info.plist to request permission.

Example: Fetching Photos from Library

import Photos

func fetchRecentPhotos() {
    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    
    let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
    
    for i in 0..<fetchResult.count {
        let asset = fetchResult.object(at: i)
        print("Photo ID: \(asset.localIdentifier)")
    }
}
PHAsset Property Description Usage
localIdentifier Unique identifier for asset Use to reference specific photo
creationDate Date photo was created Sorting and filtering
mediaType Type of media (image, video) Filter assets by type
pixelWidth Width in pixels For image size calculations
pixelHeight Height in pixels For image size calculations

Example: Saving Photo to Library

import Photos

func saveImageToPhotoLibrary(image: UIImage) {
    PHPhotoLibrary.shared().performChanges({
        PHAssetChangeRequest.creationRequestForAsset(from: image)
    }) { success, error in
        if success {
            print("Image saved successfully")
        } else {
            print("Failed to save image: \(error?.localizedDescription ?? "Unknown error")")
        }
    }
}
Warning: Saving to the photo library requires PHPhotoLibrary.requestAuthorization(for: .readWrite) to be called and authorized before attempting to save.

9. Saving Images to Photo Library

Property Value Description
PHPhotoLibrary.shared().performChanges Void Saves image to the photo library

Example: Saving an Image to Photo Library

import Photos

guard let image = UIImage(named: "exampleImage") else { return }

PHPhotoLibrary.shared().performChanges({
    PHAssetChangeRequest.creationRequestForAsset(from: image)
}) { success, error in
    if success {
        print("Image saved successfully")
    } else {
        print("Error saving image: \(error?.localizedDescription ?? "Unknown error")")
    }
}
Note: Ensure you have added the NSPhotoLibraryAddUsageDescription key to your Info.plist for iOS 14+.

10. Fetching Photos with PHAsset

Property Description Example
localIdentifier Unique identifier for the asset within the Photos library PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil)
mediaType Type of media (photo, video, audio) .image for photos, .video for videos
mediaSubtypes Subtype of media (e.g., burst, live photo) .photoLive for Live Photos
pixelWidth / pixelHeight Dimensions of the image in pixels asset.pixelWidth
creationDate Date the asset was created asset.creationDate
location Geolocation data of the asset (if available) asset.location

Example: Fetching a Photo Asset

import Photos

let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]

let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)

if let asset = fetchResult.firstObject {
    print("Local Identifier: \(asset.localIdentifier)")
    print("Media Type: \(asset.mediaType.rawValue)")
    print("Creation Date: \(asset.creationDate ?? Date())")
}
Note: You must request permission to access the Photos library using PHPhotoLibrary.requestAuthorization before fetching assets.

Example: Fetching Multiple Assets

import Photos

let identifiers = ["identifier1", "identifier2", "identifier3"]
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)

fetchResult.enumerateObjects { (asset, index, stop) in
    print("Photo at index \(index): \(asset.localIdentifier)")
}

11. Using Live Photos (PHLivePhoto)

Property Value Description
PHLivePhoto PHLivePhoto Represents a live photo asset in the Photos framework
PHLivePhoto.requesting PHLivePhotoRequestOptions Options for requesting live photo data, including preferred dimensions and delivery mode

Example: Requesting a Live Photo

import Photos

let livePhotoOptions = PHLivePhotoRequestOptions()
livePhotoOptions.deliveryMode = .opportunistic

PHImageManager.default().requestLivePhoto(
    for: photoAsset,
    options: livePhotoOptions
) { livePhoto, info in
    if let livePhoto = livePhoto {
        // Use the live photo asset
        print("Live photo requested successfully")
    }
}
Note: Live Photos are only available on devices that support them and when the user has granted appropriate permissions.

Was this article helpful?