Skip to content

Instantly share code, notes, and snippets.

@ashishkanani
Created November 28, 2022 15:16
Show Gist options
  • Save ashishkanani/86127cf302063b0442eef9b6e237f926 to your computer and use it in GitHub Desktop.
Save ashishkanani/86127cf302063b0442eef9b6e237f926 to your computer and use it in GitHub Desktop.
//
// MediaPicker.swift
//
/*
The last step you must open info.plist in your Xcode project. By write dictinary value as follow
key → Privacy - Camera Usage Description, value → $(PRODUCT_NAME) Camera use.
key → Privacy - Photo Library Usage Description, value → $(PRODUCT_NAME) Photo use.
*/
import Foundation
import UIKit
import MobileCoreServices
import AVKit
enum MediaType {
case image
case video
case media
case file
}
struct Constants {
static let photoCamera = "Photo Camera"
static let videoCamera = "Video Camera"
static let photoGallery = "Photo Gallery"
static let videoGallery = "Video Gallery"
static let file = "File"
static let cancel = "Cancel"
static let documentTypes = ["com.microsoft.word.doc", "public.data", "org.openxmlformats.wordprocessingml.document", kUTTypePDF as String] //Use for specify type you need to pickup
}
class MediaPicker: NSObject { //Inherit NSObject
static let shared: MediaPicker = MediaPicker() //Singleton Pattern
fileprivate var currentViewController: UIViewController!
var imagePickerBlock: ((_ image: UIImage, _ url: URL?) -> Void)?
var videoPickerBlock: ((_ data: Data?, _ thumbNail: UIImage) -> Void)?
var filePickerBlock: ((_ url: URL) -> Void)?
}
extension MediaPicker {
func showActionSheet(viewController: UIViewController, type: MediaType) {
currentViewController = viewController
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let photoCamera = UIAlertAction(title: Constants.photoCamera, style: .default, handler: { (action) -> Void in
self.photoCamera()
})
let videoCamera = UIAlertAction(title: Constants.videoCamera, style: .default, handler: { (action) -> Void in
self.videoCamera()
})
let photoGallery = UIAlertAction(title: Constants.photoGallery, style: .default, handler: { (action) -> Void in
self.photoGallary()
})
let videoGallery = UIAlertAction(title: Constants.videoGallery, style: .default, handler: { (action) -> Void in
self.videoGallary()
})
let file = UIAlertAction(title: Constants.file, style: .default, handler: { (action) -> Void in
self.file()
})
let cancel = UIAlertAction(title: Constants.cancel, style: .cancel, handler: nil)
if type == .image {
actionSheet.addAction(photoCamera)
actionSheet.addAction(photoGallery)
} else if type == .video {
actionSheet.addAction(videoCamera)
actionSheet.addAction(videoGallery)
} else if type == .media {
actionSheet.addAction(photoCamera)
actionSheet.addAction(photoGallery)
actionSheet.addAction(videoCamera)
actionSheet.addAction(videoGallery)
} else if type == .file {
actionSheet.addAction(file)
}
actionSheet.addAction(cancel)
viewController.present(actionSheet, animated: true, completion: nil)
}
}
extension MediaPicker: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
// currentViewController.dismiss(animated: true, completion: nil)
picker.dismiss(animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true, completion: nil)
if let image = info[.editedImage] as? UIImage {
let imageURL = info[.imageURL] as? URL
imagePickerBlock?(image, imageURL) //return image when not null
} else if let image = info[.originalImage] as? UIImage {
let imageURL = info[.imageURL] as? URL
imagePickerBlock?(image, imageURL) //return image when not null
} else if let image = info[.imageURL] as? UIImage {
imagePickerBlock?(image, nil) //return image when not null
} else if let videoUrl = info[.mediaURL] as? URL {
let thumbNail = generateThumbnail(path: videoUrl) ?? UIImage(named: "img_woooba_ball")!
let data = try? Data(contentsOf: videoUrl)
videoPickerBlock?(data, thumbNail) //return video url when not null
}
// currentViewController.dismiss(animated: true, completion: nil)
}
}
extension MediaPicker: UIDocumentMenuDelegate, UIDocumentPickerDelegate {
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
currentViewController.present(documentPicker, animated: true, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
controller.delegate = self
currentViewController.present(controller, animated: true, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
filePickerBlock?(url) //return file url if you selected from drive.
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
controller.dismiss(animated: true, completion: nil)
}
}
extension MediaPicker {
fileprivate func photoCamera() {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let pickerController = UIImagePickerController()
pickerController.allowsEditing = false
pickerController.delegate = self;
pickerController.sourceType = .camera
currentViewController.present(pickerController, animated: true, completion: nil)
}
}
fileprivate func videoCamera() {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.allowsEditing = false
pickerController.sourceType = .camera
pickerController.mediaTypes = [kUTTypeMovie as String, kUTTypeVideo as String]
pickerController.videoMaximumDuration = 10
currentViewController.present(pickerController, animated: true, completion: nil)
}
}
fileprivate func photoGallary() {
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
let pickerController = UIImagePickerController()
pickerController.delegate = self;
pickerController.allowsEditing = false
pickerController.sourceType = .photoLibrary
currentViewController.present(pickerController, animated: true, completion: nil)
}
}
fileprivate func videoGallary() {
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.allowsEditing = true
pickerController.sourceType = .photoLibrary
pickerController.mediaTypes = [kUTTypeMovie as String, kUTTypeVideo as String]
pickerController.videoMaximumDuration = 10
currentViewController.present(pickerController, animated: true, completion: nil)
}
}
fileprivate func file() {
let importMenuViewController = UIDocumentPickerViewController(documentTypes: Constants.documentTypes, in: .import)
importMenuViewController.delegate = self
importMenuViewController.modalPresentationStyle = .formSheet
currentViewController.present(importMenuViewController, animated: true, completion: nil)
}
}
/*
// How to usage.
class MockupViewController: UIViewController {
private var image: UIImage?
private var video: Data?
private var file: URL?
override func viewDidLoad() {
super.viewDidLoad()
MediaPicker.shared.showActionSheet(viewController: self, type: .all)
//Receive Image
MediaPicker.shared.imagePickerBlock = { (image, _) -> Void in
self.image = image
}
//Receive Video
MediaPicker.shared.videoPickerBlock = { (video) -> Void in
self.video = video
}
//Receive File
MediaPicker.shared.filePickerBlock = { (file) -> Void in
self.file = file
}
}
}
*/
extension MediaPicker {
func generateThumbnail(path: URL) -> UIImage? {
do {
let asset = AVURLAsset(url: path, options: nil)
let imgGenerator = AVAssetImageGenerator(asset: asset)
imgGenerator.appliesPreferredTrackTransform = true
let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
let thumbnail = UIImage(cgImage: cgImage)
return thumbnail
} catch let error {
print("*** Error generating thumbnail: \(error.localizedDescription)")
return nil
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment