iOS 11双击图像将解除UIImagePickerController和presenter视图控制器

iOS 11双击图像将解除UIImagePickerController和presenter视图控制器,ios,swift,ios11,Ios,Swift,Ios11,我们有一个用UIImagePickerController制作的照片采集器 制作双击时,点击(而不是one点击)多媒体资料中的照片 在iOS 10上:UIImagePickerController被解除 在iOS 11上:UIImagePickerController被解除,并且显示视图控制器也被解除:0 是iOS 11错误还是我们必须调整 我们的守则: let vc = UIImagePickerController() vc.delegate = self vc.modal

我们有一个用
UIImagePickerController
制作的照片采集器

制作双击时,点击(而不是one点击)多媒体资料中的照片

  • 在iOS 10上:
    UIImagePickerController
    被解除
  • 在iOS 11上:
    UIImagePickerController
    被解除,并且显示视图控制器也被解除:0
是iOS 11错误还是我们必须调整


我们的守则:

  let vc = UIImagePickerController()
  vc.delegate = self
  vc.modalPresentationStyle = .overFullScreen
  vc.allowsEditing = false
  rootVC.present(vc, animated: true) // `rootVC` also presented modally.

我们最终的解决方案是:在代理调用
did完成pickingMediaWithInfo
后立即设置
delegate=nil

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 /// It prevents to call delegate when user taps on a few images very fast. seems iOS 11 issue only.
      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?()
      }
   }
}
用法:

  // Somewhere in view controller code.
  imagePicker = ImagePicker()
  imagePicker?.present(on: self) { [weak self] in
     self?.imagePicker = nil
     self?.viewModel.addImage($0)
  }
使用picker.disclease()代替self.disclease()


这只会关闭选择器视图,而不会关闭视图控制器。

我也面临同样的问题,可能是错误。解决了吗?如果使用Dismise方法的完成处理程序执行进一步的活动,请更新答案,例如[self DismissViewControllerInitiated:YES completion:^{[self-saveImage:image];}];我们通过在委托调用之后立即设置
delegate=nil
进行修复。请参阅下面的新答案。将委托设置为零在设备上似乎不起作用。问题是didFinishPickingMediaWithInfo会被多次调用,因此如果我们在didFinishPickingMediaWithInfo中使用Disclose,它会被多次调用,从而导致出现问题您是否在
completionHandler
的回调中为您调用Disclose<代码>解除仅在
选择器上调用
。示例代码已更新。这实际上对我不起作用,因为当双击照片时,委托方法似乎不会被调用两次。相反,图像采集器似乎在自我否定。具体地说,如果我注释掉picker.discome…它仍然会在调用didSelectImage委托方法后关闭picker。注意:在我的场景中,委托被解除分配,作为初始调用选择器回调的副作用。在双击过程中,图像选择器控制器可能会决定自行关闭。事实似乎确实如此,因为阻止释放委托会阻止选择器关闭显示视图控制器。
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
    //self.dismiss(animated: true, completion: nil)
    picker.dismiss(animated: true, completion: nil)
}