Reputation: 140
I have a project which has many viewControllers using imagePicker. For each time, I have to copy the didFinishPickingMediaWithInfo again and only change some code.
Then I decided to wrap the UIImagePickerControllerDelegate and UINavigationControllerDelegate into my own protocol and extend this protocol to achieve didFinishPickingMediaWithInfo. However, the didFinishPickingMediaWithInfo is not being called at all. All the other parts work well, the image picker and camera view show well, but after finish picking, the didFinish function not being called.
I saw few suggestions online, like this one. They use the concrete class to warp the two protocols, instead of the interface.
https://gist.github.com/rpassis/4622291029cd12e4ce2b7585d3e62d15
I don't know why my solution is wrong, could someone tell me the reason why my code is wrong. Maybe I misunderstand some parts of protocol and protocol extension. BTW, I find out one warning which is
Non-'@objc' method 'imagePickerController(_:didFinishPickingMediaWithInfo:)' does not satisfy optional requirement of '@objc' protocol 'UIImagePickerControllerDelegate'
Another explanation is from Swift protocol implementing another @objc protocol
My code is shown below.
public protocol ImagePickerDelegate: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func successActionFromCamera(with localIdentifier: String, picker: UIImagePickerController)
func successActionFromPhotoLibrary(with imageURL: URL, picker: UIImagePickerController)
}
Extension to my custom Delegate
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)
}
}
}
The function to present 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)
}
}
Upvotes: 1
Views: 1021
Reputation: 140
This question is duplicated. It is actually not an ImagePicker problem, and it is more like a protocol extension problem. The reason is swift protocol cannot extend objc protocol.
I think I've already given the solution and explanation in my question.
Explanations:
Solution: https://gist.github.com/rpassis/4622291029cd12e4ce2b7585d3e62d15
I will change my code by following the solution above, if you have any new idea, please reply me. Thanks a lot.
Upvotes: 1