У меня есть проект, в котором много viewControllers, использующих imagePicker. Каждый раз мне приходится снова копировать didFinishPickingMediaWithInfo и изменять только некоторый код.
Затем я решил обернуть UIImagePickerControllerDelegate и UINavigationControllerDelegate в свой собственный протокол и расширить этот протокол для достижения didFinishPickingMediaWithInfo. Однако didFinishPickingMediaWithInfo вообще не вызывается. Все остальные части работают хорошо, средство выбора изображения и вид камеры отображаются хорошо, но после завершения выбора функция didFinish не вызывается.
Я видел несколько предложений в Интернете, таких как это. Они используют конкретный класс для деформации двух протоколов вместо интерфейса.
https://gist.github.com/rpassis/4622291029cd12e4ce2b7585d3e62d15
Я не знаю, почему мое решение неверно, может ли кто-нибудь сказать мне причину, по которой мой код неправильный. Возможно, я неправильно понимаю некоторые части протокола и расширения протокола. Кстати, я обнаружил одно предупреждение, которое
Не - '@ objc' метод 'imagePickerController (_: didFinishPickingMediaWithInfo :)' не удовлетворяет необязательному требованию протокола '@objc' UIImagePickerControllerDelegate '
Другое объяснение взято из протокола Swift, реализующего другой протокол @objc
Мой код показан ниже.
public protocol ImagePickerDelegate: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func successActionFromCamera(with localIdentifier: String, picker: UIImagePickerController)
func successActionFromPhotoLibrary(with imageURL: URL, picker: UIImagePickerController)
}
Расширение моего пользовательского делегата
extension ImagePickerDelegate {
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//camera
if info[UIImagePickerControllerReferenceURL] == nil {
func savePhotoAndTakeAction() {
var imagePlaceholder:PHObjectPlaceholder!
DispatchQueue.global(qos: .default).async {
PHPhotoLibrary.shared().performChanges({
let request = PHAssetChangeRequest.creationRequestForAsset(from: info[UIImagePickerControllerOriginalImage]! as! UIImage)
imagePlaceholder = request.placeholderForCreatedAsset!
}, completionHandler: { (success, error) -> Void in
DispatchQueue.main.async {
if success {
//image saved to photos library.
self.successActionFromCamera(with: imagePlaceholder.localIdentifier, picker: picker)
} else {
picker.dismiss(animated: true, completion: nil)
print(error!.localizedDescription)
}
picker.dismiss(animated: true, completion: nil)
}
})
}
}
switch PHPhotoLibrary.authorizationStatus() {
case .denied:
picker.dismiss(animated: false) { BasePhotoUtil.showAccessAlertController(false) }
return
case .notDetermined:
PHPhotoLibrary.requestAuthorization({ (newStatus) in
if (newStatus == .authorized) {
savePhotoAndTakeAction()
}
else {
DispatchQueue.main.async {
picker.dismiss(animated: false, completion: { BasePhotoUtil.showAccessAlertController(false) })
}
return
}
})
default:
break
}
savePhotoAndTakeAction()
} else {
//photo library
if let imageURL = info[UIImagePickerControllerReferenceURL] as? URL {
self.successActionFromPhotoLibrary(with: imageURL, picker: picker)
} else {
picker.dismiss(animated: true, completion: nil)
}
}
}
Функция для представления ImagePicker
private static func showImagePickerView(isCamera: Bool, currentVC: UIViewController) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = currentVC as? UIImagePickerControllerDelegate & UINavigationControllerDelegate
imagePicker.allowsEditing = false
imagePicker.navigationBar.isTranslucent = false
if isCamera {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePicker.sourceType = .camera
imagePicker.cameraCaptureMode = .photo
} else {
BaseAlertUtil.showNoFunctionAlertController(title: "No Camera", message: "Sorry, this device has no camera")
}
} else {
imagePicker.sourceType = .photoLibrary
}
currentVC.present(imagePicker, animated: true) {
BaseThemeUtil.setStatusBarStyle(.default)
}
}