簡體   English   中英

UIImagePickerController 委托未調用 Swift 3

[英]UIImagePickerController delegate not called 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
}

我不得不直接從委托中復制方法名稱。 出於某種原因,自動完成的方法頭錯誤。

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

細節

  • Xcode 9.2,斯威夫特 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)
    }
}

我發現委托代碼必須在活動的 UIViewController 中。

我最初嘗試將我的代碼放在一個單獨的文件中,就像聲明了正確委托協議的 NSObject 一樣,如下所示:

class PhotoPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

但這從未調用過委托方法。

使用完全相同的代碼並將其放置在我調用它的 UIViewController 中使其工作。

看起來最好的解決方案是創建一個彈出式視圖,並讓其 ViewController 保留代碼。

我也遇到了這個問題並通過使用以下解決方案解決了它。 當前完成后設置選擇器的委托。

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

希望這對你有用!!

你必須確保 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!)
                }
            })
    ....
        }

根據我的經驗,這是ARC的問題。

如果我們將實例定義為本地,那么一旦方法范圍結束,ARC 將自動刪除其引用。 如果您全局定義,則它會保留在內存中,直到視圖控制器未取消初始化。

簡答:

全局定義UIImagePickerController實例。

長答案:

我已經創建了一次NSObject的公共類和UIImagePickerController delegates方法未被調用。

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

這段代碼有效(盡管它會一遍又一遍地重新顯示,因為它在 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)
    }
}

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

我投了這個票,因為我錯過了UINavgationControllerDelegate聲明,這個評論有幫助。

沒有調用imagePickerController

我發現對我有幫助的是確保將委托設置為public而不是private

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM