UIImagePickerController委托不叫Swift 3

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

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

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

不适合我。 'picker'在'handler'被调用之前被释放了。

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

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!)
                }
            })
    ....
        }
2
投票

我也遇到了这个问题,并通过使用以下解决方案解决了它。目前完成后设置选择器的代表。

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

希望这对你有用!!

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)
    }
}
1
投票

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

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

class PhotoPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

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

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

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

0
投票

我投了这个,因为我错过了UINavgationControllerDelegate声明,这个评论有所帮助。

imagePickerController没有被召唤。