As a result, we get the solution: install delegate = nil
immediately after calling the delegate to didFinishPickingMediaWithInfo
.
public class ImagePicker: NSObject {
private lazy var viewController = setupActionSheet()
private var rootViewController: UIViewController?
private var completionHandler: (([String: Any]) -> Void)?
private var cancellationHandler: (() -> Void)?
}
extension ImagePicker {
public func present(on: UIViewController, completionHandler: @escaping (([String: Any]) -> Void)) {
rootViewController = on
self.completionHandler = completionHandler
cancellationHandler = nil
on.presentAnimated(viewController)
}
public func present(on: UIViewController,
completionHandler: @escaping (([String: Any]) -> Void),
cancellationHandler: @escaping (() -> Void)) {
rootViewController = on
self.completionHandler = completionHandler
self.cancellationHandler = cancellationHandler
on.presentAnimated(viewController)
}
}
extension ImagePicker {
private func setupActionSheet() -> UIAlertController {
let actionSheet = UIAlertController(actionSheetWithTitle: LocalizedString.Generic.ImagePicker.addPhoto)
if UIImagePickerController.isSourceTypeAvailable(.camera) {
actionSheet.addDefaultAction(LocalizedString.Generic.ImagePicker.takePhoto) { [weak self] _ in
self?.presentImagePicker(.camera)
}
}
actionSheet.addDefaultAction(LocalizedString.Generic.ImagePicker.selectPhoto) { [weak self] _ in
self?.presentImagePicker(.photoLibrary)
}
actionSheet.addCancelAction(LocalizedString.Generic.ButtonTitle.cancel) { [weak self] _ in
self?.cancellationHandler?()
}
return actionSheet
}
private func presentImagePicker(_ sourceType: UIImagePickerControllerSourceType) {
let vc = UIImagePickerController()
vc.delegate = self
vc.allowsEditing = false
vc.sourceType = sourceType
rootViewController?.present(vc, animated: true)
}
}
extension ImagePicker: UIImagePickerControllerDelegate {
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {
picker.delegate = nil
if picker.sourceType == .camera, let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}
picker.dismiss(animated: true) {
self.completionHandler?(info)
}
}
public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true) {
self.cancellationHandler?()
}
}
}
Using:
imagePicker = ImagePicker()
imagePicker?.present(on: self) { [weak self] in
self?.imagePicker = nil
self?.viewModel.addImage($0)
}
source
share