Skip to content

Instantly share code, notes, and snippets.

@JasonCanCode
Created November 28, 2018 21:53
Show Gist options
  • Save JasonCanCode/cfc89254e7b9a007b8912a18afaa7d65 to your computer and use it in GitHub Desktop.
Save JasonCanCode/cfc89254e7b9a007b8912a18afaa7d65 to your computer and use it in GitHub Desktop.
Helper protocol for populating an image view with a taken photo or one from the library.
import AVFoundation
import MobileCoreServices
import Photos
import UIKit
enum CaptureError: Error {
case cameraUnavailable
case cameraDenied
case libraryUnavailable
}
extension CaptureError: LocalizedError {
var localizedDescription: String {
switch self {
case .cameraUnavailable:
return NSLocalizedString("Unable to access your camera for video recording.", comment: "")
case .cameraDenied:
return NSLocalizedString("Access to the device's camera has been denied.", comment: "")
case .libraryUnavailable:
return NSLocalizedString("Please grant access to your Photo Library.", comment: "")
}
}
}
protocol PhotoImageUpdatable: class, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var photoImageView: UIImageView! { get set }
/// Call `updateImageAndDismiss(picker: picker, withInfo: info)` when this is called
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any])
}
extension PhotoImageUpdatable where Self: UIViewController {
func showPhotoOptionActionSheet() {
let uploadPhotoRollOption = NSLocalizedString("Photo Roll", comment: "")
let uploadCameraOption = NSLocalizedString("Take Picture", comment: "")
let cancelOption = NSLocalizedString("Cancel", comment: "")
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let photoRollAction = UIAlertAction(title: uploadPhotoRollOption, style: .default, handler: { (_: UIAlertAction!) -> Void in
self.presentPhotoRoll()
})
let takePictureAction = UIAlertAction(title: uploadCameraOption, style: .default, handler: { (_: UIAlertAction!) -> Void in
self.takePicture()
})
let cancelAction = UIAlertAction(title: cancelOption, style: .cancel, handler: nil)
optionMenu.addAction(photoRollAction)
optionMenu.addAction(takePictureAction)
optionMenu.addAction(cancelAction)
self.present(optionMenu, animated: true, completion: nil)
}
func presentPhotoRoll() {
let sourceType = UIImagePickerControllerSourceType.photoLibrary
guard UIImagePickerController.isSourceTypeAvailable(sourceType) else {
showAlert(for: .libraryUnavailable)
return
}
switch PHPhotoLibrary.authorizationStatus() {
case .notDetermined:
PHPhotoLibrary.requestAuthorization() { status in
if status == .authorized {
self.presentImagePicker(sourceType: sourceType)
} else {
self.showAlert(for: .libraryUnavailable)
}
}
case .authorized:
presentImagePicker(sourceType: sourceType)
default:
showAlert(for: .libraryUnavailable)
}
}
func takePicture() {
let sourceType = UIImagePickerControllerSourceType.camera
guard UIImagePickerController.isSourceTypeAvailable(sourceType) else {
showAlert(for: .cameraUnavailable)
return
}
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { granted in
if granted {
self.presentImagePicker(sourceType: sourceType)
} else {
self.showAlert(for: .cameraDenied)
}
}
case .denied:
showAlert(for: .cameraDenied)
case .restricted:
showAlert(for: .cameraUnavailable)
case .authorized:
presentImagePicker(sourceType: sourceType)
}
}
private func presentImagePicker(sourceType: UIImagePickerController.SourceType) {
guard UIImagePickerController.isSourceTypeAvailable(sourceType) else {
return
}
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = sourceType
imagePicker.allowsEditing = true
imagePicker.mediaTypes = [kUTTypeImage as String]
if sourceType == .camera {
imagePicker.cameraCaptureMode = .photo
}
present(imagePicker, animated: true, completion: nil)
}
private func showAlert(for error: CaptureError) {
let errorTitle = NSLocalizedString("Permissions Error", comment: "")
let message = error.localizedDescription
AlertHelper.showSettingsAlert(in: self, title: errorTitle, message: message)
}
func updateImageAndDismiss(picker: UIImagePickerController, withInfo info: [String: Any]) {
let pickedImage = info[UIImagePickerControllerEditedImage] as? UIImage
?? info[UIImagePickerControllerOriginalImage] as? UIImage
photoImageView.image = pickedImage ?? photoImageView.image
view.setNeedsLayout()
picker.dismiss(animated: true, completion: nil)
}
}
@JasonCanCode
Copy link
Author

Makes use of AlertHelper

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment