Created
November 28, 2018 21:53
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Makes use of
AlertHelper