Created
November 2, 2015 10:07
-
-
Save gabro/a73f61a6e54e02ecbb17 to your computer and use it in GitHub Desktop.
A block-based asset picker for videos, photos and files
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 Photos | |
import MobileCoreServices | |
class AssetPicker: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIDocumentPickerDelegate, UIDocumentMenuDelegate { | |
static let sharedInstance = AssetPicker() | |
private lazy var cameraPicker: UIImagePickerController = { | |
let cameraPicker = UIImagePickerController() | |
cameraPicker.delegate = self | |
cameraPicker.sourceType = .Camera | |
cameraPicker.allowsEditing = true | |
return cameraPicker | |
}() | |
private lazy var videoCameraPicker: UIImagePickerController = { | |
let cameraPicker = UIImagePickerController() | |
cameraPicker.delegate = self | |
cameraPicker.sourceType = .Camera | |
cameraPicker.allowsEditing = true | |
cameraPicker.mediaTypes = [String(kUTTypeMovie)] | |
return cameraPicker | |
}() | |
private lazy var singlePhotoPicker: UIImagePickerController = { | |
let imagePicker = UIImagePickerController() | |
imagePicker.sourceType = .PhotoLibrary | |
imagePicker.delegate = self | |
imagePicker.allowsEditing = true | |
return imagePicker | |
}() | |
private lazy var singleVideoPicker: UIImagePickerController = { | |
let videoPicker = UIImagePickerController() | |
videoPicker.sourceType = .PhotoLibrary | |
videoPicker.delegate = self | |
videoPicker.allowsEditing = true | |
videoPicker.mediaTypes = [String(kUTTypeMovie)] | |
return videoPicker | |
}() | |
private func takePhotoAction(vc: UIViewController) -> UIAlertAction { | |
return UIAlertAction(title: "Take a photo", style: .Default) { _ in | |
vc.presentViewController(self.cameraPicker, animated: true, completion: nil) | |
} | |
} | |
private func chooseSinglePhotoFromLibraryAction(vc: UIViewController) -> UIAlertAction { | |
return UIAlertAction(title: "Choose from library", style: .Default) { _ in | |
vc.presentViewController(self.singlePhotoPicker, animated: true, completion: nil) | |
} | |
} | |
private func takeVideoAction(vc: UIViewController) -> UIAlertAction { | |
return UIAlertAction(title: "Take a video", style: .Default) { _ in | |
vc.presentViewController(self.videoCameraPicker, animated: true, completion: nil) | |
} | |
} | |
private func chooseSingleVideoFromLibraryAction(vc: UIViewController) -> UIAlertAction { | |
return UIAlertAction(title: "Choose from library", style: .Default) { _ in | |
vc.presentViewController(self.singleVideoPicker, animated: true, completion: nil) | |
} | |
} | |
private let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil) | |
private var pickSinglePhotoCompletionHandler: (UIImage? -> Void)? | |
private var pickSingleVideoCompletionHandler: (NSURL? -> Void)? | |
private var pickFileCompletionHandler: (NSURL? -> Void)? | |
private var viewController: UIViewController? | |
func pickPhoto(inViewController vc: UIViewController, sourceView: UIView? = nil, buttonItem: UIBarButtonItem? = nil, completionHandler: UIImage? -> Void) { | |
self.pickSinglePhotoCompletionHandler = completionHandler | |
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) | |
if UIImagePickerController.isSourceTypeAvailable(.Camera) { | |
alert.addAction(takePhotoAction(vc)) | |
} | |
alert.addAction(chooseSinglePhotoFromLibraryAction(vc)) | |
alert.addAction(cancelAction) | |
if UIDevice.currentDevice().userInterfaceIdiom == .Pad { | |
assert(sourceView != nil || buttonItem != nil, | |
"You must provide either sourceView or buttonItem to \(__FUNCTION__) when on an iPad") | |
alert.popoverPresentationController?.sourceView = sourceView | |
alert.popoverPresentationController?.barButtonItem = buttonItem | |
if let sourceView = sourceView { | |
alert.popoverPresentationController?.sourceRect = sourceView.bounds | |
} | |
} | |
vc.presentViewController(alert, animated: true, completion: nil) | |
} | |
func pickVideo(inViewController vc: UIViewController, sourceView: UIView? = nil, buttonItem: UIBarButtonItem? = nil, completionHandler: NSURL? -> Void) { | |
self.pickSingleVideoCompletionHandler = completionHandler | |
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) | |
if UIImagePickerController.isSourceTypeAvailable(.Camera) { | |
alert.addAction(takeVideoAction(vc)) | |
} | |
alert.addAction(chooseSingleVideoFromLibraryAction(vc)) | |
alert.addAction(cancelAction) | |
if UIDevice.currentDevice().userInterfaceIdiom == .Pad { | |
assert(sourceView != nil || buttonItem != nil, | |
"You must provide either sourceView or buttonItem to \(__FUNCTION__) when on an iPad") | |
alert.popoverPresentationController?.sourceView = sourceView | |
alert.popoverPresentationController?.barButtonItem = buttonItem | |
if let sourceView = sourceView { | |
alert.popoverPresentationController?.sourceRect = sourceView.bounds | |
} | |
} | |
vc.presentViewController(alert, animated: true, completion: nil) | |
} | |
func pickFile(inViewController vc: UIViewController, completionHandler: NSURL? -> Void) { | |
self.viewController = vc | |
self.pickFileCompletionHandler = completionHandler | |
let documentMenuVC = UIDocumentMenuViewController(documentTypes: [String(kUTTypeContent)], inMode: .Import) | |
documentMenuVC.delegate = self | |
vc.presentViewController(documentMenuVC, animated: true, completion: nil) | |
} | |
//MARK: UIImagePickerControllerDelegate | |
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { | |
let mediaType = info[UIImagePickerControllerMediaType] as! NSString | |
if mediaType == kUTTypeMovie { | |
let videoURL = info[UIImagePickerControllerMediaURL] as! NSURL | |
pickSingleVideoCompletionHandler?(videoURL) | |
} else { | |
let editedImage: UIImage? = info[UIImagePickerControllerEditedImage] as? UIImage | |
let originalImage: UIImage = info[UIImagePickerControllerOriginalImage] as! UIImage | |
let image = editedImage ?? originalImage | |
pickSinglePhotoCompletionHandler?(image) | |
} | |
picker.presentingViewController?.dismissViewControllerAnimated(true, completion: nil) | |
} | |
func imagePickerControllerDidCancel(picker: UIImagePickerController) { | |
pickSinglePhotoCompletionHandler?(nil) | |
picker.presentingViewController?.dismissViewControllerAnimated(true, completion: nil) | |
} | |
// MARK: UIDocumentPickerMenu | |
func documentMenu(documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) { | |
documentPicker.delegate = self | |
viewController?.presentViewController(documentPicker, animated: true, completion: nil) | |
} | |
func documentMenuWasCancelled(documentMenu: UIDocumentMenuViewController) { | |
pickFileCompletionHandler?(nil) | |
} | |
// MARK: UIDocumentPickerDelegate | |
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL) { | |
pickFileCompletionHandler?(url) | |
} | |
func documentPickerWasCancelled(controller: UIDocumentPickerViewController) { | |
pickFileCompletionHandler?(nil) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Basic usage