UIImagePickerController委托不叫Swift 3

时间:2016-09-25 02:50:00

标签: ios swift uiimagepickercontroller swift3

从表面上看,我认为这必须是代表问题,但在要求代表后,正确的一个被退回。

我创建了一个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
}

10 个答案:

答案 0 :(得分:8)

详细

  • 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)
    }
}

答案 1 :(得分:7)

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

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)
}

答案 2 :(得分:3)

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

如果我们将实例定义为本地实例,则ARC将删除其引用 一旦方法作用域结束,就会自动进行。如果全局定义的话 保留在内存中,直到未初始化视图控制器为止。

简短答案:

全局定义UIImagePickerController实例。

长答案:

我没有创建NSObjectdelegates的{​​{1}}方法的通用类。

经过5个小时的集思广益,最后,找到解决方案。似乎是与从相机捕获的图像期间内存释放有关的问题。

UIImagePickerController

答案 3 :(得分:2)

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

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

class PhotoPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

但是从未调用委托方法。

完全相同的代码放在UIViewController中我调用它使其工作。

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

答案 4 :(得分:2)

哟必须确保在委托调用之前没有发布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!)
        }
    })
....
}

对我不起作用。 &#39;选择器&#39;在处理程序&#39;之前发布可以被称为。

我创建了永久性引用,它起作用了:

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 :(得分:2)

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

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

希望这对您有用!

答案 6 :(得分:1)

此代码有效,(但是,它会反复重新显示,因为它在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)
    }
}

答案 7 :(得分:0)

我投了赞成票,因为我错过了UINavgationControllerDelegate声明,而这一评论有所帮助。

imagePickerController没有被呼叫。

答案 8 :(得分:0)

迅捷4.2 根据ViewController添加

 UIImagePickerControllerDelegate,UINavigationControllerDelegate 
   @IBOutlet weak var ImagePhoto: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    @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)
 }

答案 9 :(得分:0)

我发现对我有帮助的是确保将委托设置为 public 而不是 private

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