UIImagePickerController委托不叫Swift 3

Cla*_*ohn 11 uiimagepickercontroller ios swift 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

永远不会被称为:

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

Vas*_*huk 12

细节

Xcode 9.2,Swift 4

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

完整样本

BaseViewController.swift

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

ViewController.swift

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请不要只发布一大堆代码.一个好的答案解释了OP代码中的错误以及他们的答案如何解决问题. (9认同)

Dus*_*ler 8

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

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)
}
Run Code Online (Sandbox Code Playgroud)

  • 你是最棒的!我太努力想弄清楚这个问题,但不是简单地打电话给代表。原因 :: 方法名称略有不同:我之前使用的 :: func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { 什么有效:func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController. InfoKey : Any]) { 不幸的是,委托是可选的,所以如果你在方法上有一个小错误,你将永远无法调试它为什么不起作用。 (2认同)
  • 他们似乎改变了 Swift 5 中的方法。残酷。 (2认同)

iDe*_*750 7

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

controller.present(picker, animated: true, completion: {
            self.picker.delegate = self
        })
Run Code Online (Sandbox Code Playgroud)

希望这对你有用!


Hit*_*esh 7

根据我的经验,这是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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Nic*_*kel 5

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

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

class PhotoPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 只需为您的视图控制器全局定义 PhotoPicker 即可。一切都按预期进行! (2认同)

Vic*_*r_Z 5

你必须确保 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!)
        }
    })
....
}
Run Code Online (Sandbox Code Playgroud)

不适合我。在调用“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!)
                }
            })
    ....
        }
Run Code Online (Sandbox Code Playgroud)