I have a fairly simply NSObject class that is what I am calling a MediaPicker
. This class asks the user what type of media they want to pick and subsequently presents an UIImagePickerController
or a UIDocumentPickerViewController
based on their selection.
The problem I'm facing is that the UIImagePickerControllerDelegate
and the UIDocumentPickerViewControllerDelegate
methods are not being called.
My class is below:
import Foundation
import UIKit
import MobileCoreServices
public protocol MediaPickerDelegate: NSObjectProtocol {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any])
func imagePickerControllerDidCancel(_ picker: UIImagePickerController)
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController)
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL])
}
class MediaPicker: NSObject {
//Data
var viewController: UIViewController? = nil
var imagePicker: UIImagePickerController = UIImagePickerController()
let documentPicker = UIDocumentPickerViewController(documentTypes: [(kUTTypeImage as String), (kUTTypeMovie as String)], in: .import)
//Delegate
weak var delegate: MediaPickerDelegate? = nil
override init() {
super.init()
}
public func showMediaPicker(from presentingViewController: UIViewController) {
//Set Data
self.viewController = presentingViewController
//Create Alert
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
//Add Library Action
let libraryAction: UIAlertAction = UIAlertAction(title: "Photo & Video Library", style: .default) { (action) in
self.presentLibraryPicker()
}
libraryAction.setValue(UIImage(named: "gallery_picker_library"), forKey: "image")
libraryAction.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
alertController.addAction(libraryAction)
//Add Cloud Action
let cloudAction: UIAlertAction = UIAlertAction(title: "Other Locations", style: .default) { (action) in
self.presentDocumentPicker()
}
cloudAction.setValue(UIImage(named: "gallery_picker_cloud"), forKey: "image")
cloudAction.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
alertController.addAction(cloudAction)
//Add Cancel Action
let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
//Show Alert
self.viewController?.present(alertController, animated: true, completion: nil)
}
private func presentLibraryPicker() {
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .savedPhotosAlbum) ?? []
imagePicker.allowsEditing = true
self.viewController?.present(imagePicker, animated: true, completion: nil)
}
private func presentDocumentPicker() {
documentPicker.delegate = self
documentPicker.allowsMultipleSelection = false
self.viewController?.present(documentPicker, animated: true, completion: nil)
}
}
extension MediaPicker: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
delegate?.imagePickerController(picker, didFinishPickingMediaWithInfo: info)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
delegate?.imagePickerControllerDidCancel(picker)
}
}
extension MediaPicker: UIDocumentPickerDelegate {
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
delegate?.documentPickerWasCancelled(controller)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
delegate?.documentPicker(controller, didPickDocumentsAt: urls)
}
}
extension MediaPicker: UINavigationControllerDelegate {
//Redundant delegate implented as part of UIImagePickerControllerDelegate
}
The class calling this looks like this:
class Foo: UIViewController {
@objc func openPicker() {
let mediaPicker: MediaPicker = MediaPicker()
mediaPicker.delegate = self
mediaPicker.showMediaPicker(from: self)
}
}
I've tried making the protocol
for MediaPickerDelegate
both a class
and NSObjectProtocol
but with no luck. I also tried (thinking maybe an ARC issue from my obj-c days) making the two picker variables global and local in scope to the function but this didn't seem to change anything.
I'm also open to any feedback you have on the quality of the code that's been written/best practices that I may have missed.