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.