Using the code below it opens the camera but fails to call the picker delegate method. I'm getting no error messages.
import Foundation
import UIKit
import MobileCoreServices
class RecVidController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
RecVidController.startRecord(delegate: self, sourceType: .camera)
}
static func startRecord(delegate: UIViewController & UINavigationControllerDelegate & UIImagePickerControllerDelegate, sourceType: UIImagePickerController.SourceType) {
guard UIImagePickerController.isSourceTypeAvailable(sourceType) else { return }
let mediaUI = UIImagePickerController()
mediaUI.sourceType = sourceType
mediaUI.mediaTypes = [kUTTypeMovie as String]
mediaUI.allowsEditing = true
mediaUI.delegate = delegate
delegate.present(mediaUI, animated: true, completion: nil)
}
@objc func video(_ videoPath: String, didFinishSavingWithError error: Error?, contextInfo info: AnyObject) {
let title = (error == nil) ? "Success" : "Error"
let message = (error == nil) ? "Video was saved" : "Video failed to save"
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
}
// MARK: - UIImagePickerControllerDelegate
extension RecVidController: UIImagePickerControllerDelegate {
private func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
dismiss(animated: true, completion: nil)
guard let mediaType = info[UIImagePickerController.InfoKey.mediaType] as? String,
mediaType == (kUTTypeMovie as String),
let url = info[UIImagePickerController.InfoKey.mediaURL] as? URL,
UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(url.path)
else { return }
// Handle a movie capture
UISaveVideoAtPathToSavedPhotosAlbum(url.path, self, #selector(video(_:didFinishSavingWithError:contextInfo:)), nil)
}
}
// MARK: - UINavigationControllerDelegate
extension RecVidController: UINavigationControllerDelegate {
}
The problem is this declaration:
private func imagePickerController(
_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
You have declared this method private
, so Objective-C has no way of knowing that it exists. Thus, it can't call into it.
Basically, Cocoa looks to see whether this method is implemented, discovers that it isn't (because you've hidden it), and gives up. There's no visible penalty, because this delegate method is optional, and when it is not implemented, Cocoa dismisses the picker for you when the user is finished with it.
So just delete private
and you should be good to go. This exposes the delegate method to Objective-C, and so it will be called.
(You do not have to say @objc
to expose it to Objective-C, as you would if this were your own function, because you've declared we adopt UIImagePickerControllerDelegate, which is an Objective-C protocol.)