【问题标题】:UIImagePickerController delegate not called Swift 3UIImagePickerController 委托未调用 Swift 3
【发布时间】:2016-09-25 02:50:00
【问题描述】:

表面上我认为这一定是代理问题,但在要求代理后,正确的人被退回了。

我创建了一个 ImagePicker 类来处理所有 UIImagePickerController 的东西。在需要调用委托方法之前,一切都有效。在我选择一张照片后,imagePicker 将关闭,但 didFinishPickingMediaWithInfo 方法永远不会被调用。请帮忙!谢谢:)

func selectPhoto() {
    imagePicker.delegate = self //Delegate gets set here

    let photoAsk = UIAlertController.init( //Ask user if they want to take picture or choose one
        title: "Edit Profile Picture",
        message: nil,
        preferredStyle: .alert)
    let cameraAction = UIAlertAction.init(
        title: "Take Photo",
        style: .default) { (UIAlertAction) in
            if (UIImagePickerController.isSourceTypeAvailable(.camera)) {
                self.imagePicker.sourceType = .camera
                UIApplication.topViewController()!.present(self.imagePicker, animated: true, completion:nil)
            } else {
                print("Cannot access camera in simulator.")
                return
            }
    }
    let photoLibraryAction = UIAlertAction.init(
        title: "Photo Library",
        style: .default) { (UIAlertAction) in
            self.imagePicker.sourceType = .photoLibrary
            UIApplication.topViewController()!.present(self.imagePicker, animated: true, completion:nil)
            print("UIImagePickerDelegate: \(self.imagePicker.delegate.debugDescription)") // <--THIS PRINTS OUT "AppName.ImagePicker: 0x145d7bdf0>", and the class name is ImagePicker
    }
    let cancelAction = UIAlertAction.init(
        title: "Cancel",
        style: .cancel) { (UIAlertAction) in return }

    photoAsk.addAction(cameraAction)
    photoAsk.addAction(photoLibraryAction)
    photoAsk.addAction(cancelAction)

    imagePicker.mediaTypes = [kUTTypeImage as String]

    UIApplication.topViewController()?.present(photoAsk, animated: true, completion: nil)
    }
}

这永远不会被调用:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    print("Image picked.") //NEVER PRINTS
}

【问题讨论】:

  • 尝试设置imagePicker.delegate = selfin viewDidLoadinstead
  • @RashwanL 是一个自定义类,但是我试着把它放在类的init 方法中,并没有什么区别。
  • 我很困惑。 selectPhoto() 在哪里被调用?
  • 在您的问题中发布的这个自定义类的实例是否有强烈的参考?
  • @ClaytonAndrewCohn 你有什么解决办法吗?我在 ImageHelper 类中遇到了同样的问题。

标签: ios swift uiimagepickercontroller swift3


【解决方案1】:

我不得不直接从委托中复制方法名称。由于某种原因,自动完成的方法标头错误。

public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
        //save image
        //display image
    }
    self.dismiss(animated: true, completion: nil)
}

public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
    self.dismiss(animated: true, completion: nil)
}

更新 SWIFT 5:

public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
        //save image
        //display image
    }
    self.dismiss(animated: true, completion: nil)
}

【讨论】:

  • 你是最棒的!我很努力地想弄清楚这个问题,但并不是简单地调用了代表。原因 :: 方法名称略有不同: 我之前的内容 :: func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { 什么有效: func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController. InfoKey : Any]) { 不幸的是,委托是可选的,所以如果你在方法上有一个小错误,你将永远无法调试它为什么不工作。
  • 他们似乎改变了 Swift 5 中的方法。残酷。
  • 谢谢你,你帮助了我。他们更改了方法名称,但没有提到旧方法已被弃用,Apple 干得好。
【解决方案2】:

详情

  • Xcode 9.2,Swift 4
  • Xcode 10.2.1 (10E1001)、Swift 5

解决方案

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        print("\(info)")
        if let image = info[.originalImage] as? UIImage {
            imageView?.image = image
            dismiss(animated: true, completion: nil)
        }
    }
}

用法

let imagePickerController = UIImagePickerController()
imagePickerController.allowsEditing = false
imagePickerController.sourceType = .photoLibrary
imagePickerController.delegate = self
present(imagePickerController, animated: true, completion: nil)

完整样本

不要忘记在此处添加解决方案代码(见上图)

import UIKit

class ViewController: UIViewController {

    private weak var imageView: UIImageView?

    override func viewDidLoad() {
        super.viewDidLoad()
        let stackView = UIStackView(frame: .zero)
        stackView.axis = .vertical
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)
        stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFit
        imageView.translatesAutoresizingMaskIntoConstraints = false
        stackView.addArrangedSubview(imageView)
        imageView.widthAnchor.constraint(equalToConstant: 200).isActive = true
        imageView.heightAnchor.constraint(equalToConstant: 200).isActive = true
        self.imageView = imageView

        let button = UIButton(frame: .zero)
        button.setTitle("Button", for: .normal)
        button.setTitleColor(.blue, for: .normal)
        button.addTarget(self, action: #selector(showImages), for: .touchUpInside)
        stackView.addArrangedSubview(button)
    }

    @IBAction func showImages(_ sender: AnyObject) {
        let imagePickerController = UIImagePickerController()
        imagePickerController.allowsEditing = false
        imagePickerController.sourceType = .photoLibrary
        imagePickerController.delegate = self
        present(imagePickerController, animated: true, completion: nil)
    }
}

【讨论】:

  • 请不要只发布一大堆代码。一个好的答案解释了 OP 代码中的问题以及他们的答案如何解决问题。
  • 好的。但在这个问题上,我们有很多时刻要解释。我的英语不是很完美,所以,我决定创建完整的样本。下次,我会尝试你的建议。谢谢!
  • 另外,@VasilyBodnarchuk,我知道将委托及其方法放在我的调用视图控制器中是可行的。我想做的是创建一个辅助类来充当委托,因为我有 3-4 个不同的视图控制器需要使用完全相同的代码,而且我不想每次切换时都重复相同的两个委托调用查看控制器。
  • 这仍然不是 UIImagePickerController/UIImagePickerDelegate 的子类。我想要做的是创建一个可以处理调用的单个子类、扩展名或文件,而不管我从哪个视图控制器调用它
【解决方案3】:

我发现委托代码必须在活动的 UIViewController 中。

我最初试图将我的代码放在一个单独的文件中,就像声明了正确委托协议的 NSObject 一样,如下所示:

class PhotoPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

但这从未调用过委托方法。

采用 exact 相同的代码并将其放置在我调用它的 UIViewController 中使其工作。

看起来最好的解决方案是创建一个弹出式视图,并让其 ViewController 保留代码。

【讨论】:

  • 只需为您的视图控制器全局定义 PhotoPicker。一切都按预期工作!
  • @IMHiteshSurani 很好的回答,它也可以工作。你能解释一下为什么在全球和本地声明会产生这样的效果
  • @HarshThakur 在此处添加了详细说明stackoverflow.com/a/59930383/5036586
【解决方案4】:

你必须确保 UIImagePickerController 在委托调用之前没有被释放。

我创建了一个 ImagePicker 类来处理所有 UIImagePickerController 的东西。

我创建了类似的课程,但是

func onButtonDidTap(sender: UIButton) {
.....
    let picker = VLImagePickerController()
    picker.show(fromSender: sender, handler: { (image: UIImage?) -> (Void) in
        if (image != nil) {
            self.setImage(image!)
        }
    })
....
}

对我不起作用。 在调用 'handler' 之前释放了 'picker'。

我创建了永久引用,并且成功了:

let picker = VLImagePickerController()

    func onButtonDidTap(sender: UIButton) {
    .....
            //let picker = VLImagePickerController()
            picker.show(fromSender: sender, handler: { (image: UIImage?) -> (Void) in
                if (image != nil) {
                    self.setImage(image!)
                }
            })
    ....
        }

【讨论】:

  • 这发生在我身上...不要将图像选择器保持为弱或函数中的实例变量...最好将其添加为属性
【解决方案5】:

我也遇到了这个问题,并通过使用以下解决方案解决了这个问题。在当前完成后设置选取器的委托。

controller.present(picker, animated: true, completion: {
            self.picker.delegate = self
        })

希望这对你有用!!

【讨论】:

    【解决方案6】:

    根据我的经验,这是 ARC 的问题。

    如果我们将实例定义为本地实例,那么 ARC 将删除它的引用 一旦方法范围结束自动。如果您在全局范围内定义,那么它 一直保存在内存中,直到视图控制器未被取消初始化。

    简答:

    全局定义UIImagePickerController 实例。

    长答案:

    我已经创建了一次NSObjectdelegates 的公共类UIImagePickerController 的方法未被调用。

    经过 5 个小时的头脑风暴,终于得到了解决方案。在从相机捕获图像期间,这似乎是与内存释放有关的问题。

    public typealias CameraBlock = (UIImage?, Bool) -> Void
    
    class HSCameraSingleton: NSObject {
        
        var pickerController = UIImagePickerController()
        private var completionBlock: CameraBlock!
        var presentationController: UIViewController?
        
        public init(presentationController: UIViewController) {
            super.init()
            self.presentationController = presentationController
        }
        
        
        public func present(completionBlock: @escaping CameraBlock) {
            guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
                return
            }
            
            self.pickerController = UIImagePickerController()
            self.pickerController.delegate = self
            self.pickerController.allowsEditing = true
            self.pickerController.sourceType = .camera
            self.completionBlock = completionBlock
            self.presentationController?.present(self.pickerController, animated: true, completion: nil)
        }
    }
    
    
    extension HSCameraSingleton: UIImagePickerControllerDelegate,UINavigationControllerDelegate {
        
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            self.completionBlock?(nil,false)
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            guard let image = info[.originalImage] as? UIImage else {
                self.completionBlock?(nil,false)
                return
            }
            self.completionBlock?(image,true)
            pickerController.dismiss(animated:true, completion: nil)
        }
    }
    
    
    class AuthViewController: UIViewController{
    
    lazy var overlay = HSCameraSingleton(presentationController:self)
    
    @IBAction func actionLoginTap(_ sender: UIControl) {
            
            overlay.present { (image, status) in
                print(image,status)
            }
        }
    }
    

    【讨论】:

      【解决方案7】:

      此代码有效,(尽管它会一遍又一遍地重新显示,因为它会在 viewWillAppear 中显示选择器,这只是为了保持代码较小)。我会看看有什么不同。它可能与您的顶视图控制器有关?为什么不直接从视图控制器显示选择器而不是转到应用程序的顶部视图控制器?此外,一旦您获得委托回调,您需要关闭视图控制器。

      import UIKit
      import MobileCoreServices
      
      class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
          let imagePicker = UIImagePickerController()
      
          override func viewDidLoad() {
              super.viewDidLoad()
              imagePicker.mediaTypes = [kUTTypeImage as String]
              imagePicker.delegate = self
          }
      
          override func viewDidAppear(_ animated: Bool) { // keeps reopening, do not this in your code. 
              present(imagePicker, animated: true, completion: nil)
          }
      
          func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
              imagePicker.dismiss(animated: true, completion: nil)
          }
      }
      

      【讨论】:

        【解决方案8】:

        我投了这个票,因为我错过了 UINavgationControllerDelegate 声明,而这条评论很有帮助。

        imagePickerController 未被调用。

        【讨论】:

          【解决方案9】:

          我发现对我有所帮助的是确保将代理设置为 public 而不是 private

          public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
          

          【讨论】:

            【解决方案10】:

            斯威夫特 4.2

            根据ViewController添加Delegate方法

            UIImagePickerControllerDelegate,UINavigationControllerDelegate

            //IBOutlet
            @IBOutlet weak var ImagePhoto: UIImageView!
            
            override func viewDidLoad() {
                super.viewDidLoad()
            }
            
            //Button Action Take Photo
            @IBAction func btnPhotoTap(_ sender: Any) {
               
                       let imagePicker = UIImagePickerController()
                       imagePicker.delegate = self
                       imagePicker.sourceType = .photoLibrary // Or .camera as you require
                       imagePicker.allowsEditing = true
                       self.present(imagePicker, animated: true, completion: nil)
            }
            
            //MARK:-imagePickerControllerDelegate
            func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
                       let image1 =  info[UIImagePickerController.InfoKey.editedImage] as? UIImage
                       self.ImagePhoto.image = image1
                       self.dismiss(animated: true, completion: nil)
            }
            func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
               
                       print("Cancel")
                       self.dismiss(animated: true, completion: nil)
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-02-09
              • 2018-01-06
              • 1970-01-01
              • 2016-05-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多