webentwicklung-frage-antwort-db.com.de

UIImagePickerController-Delegat wird nicht als Swift 3 bezeichnet

Oberflächlich dachte ich, dass es sich hierbei um ein Delegatenthema handeln musste, aber nachdem ich nach dem Delegierten gefragt hatte, wurde das richtige zurückgegeben.

Ich habe eine ImagePicker-Klasse erstellt, um alle UIImagePickerController-Sachen zu verarbeiten. Alles funktioniert, bis die Delegatmethoden aufgerufen werden müssen. Nachdem ich ein Foto ausgewählt habe, wird der imagePicker abgelehnt, aber die didFinishPickingMediaWithInfo-Methode wird nie aufgerufen. Bitte helfen Vielen Dank :)

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

Dies wird nie genannt:

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

Einzelheiten

Xcode 9.2, Swift 4

Lösung

extension BaseViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

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

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        NSLog("\(info)")
        let image = info[UIImagePickerControllerOriginalImage] as? UIImage
        imagePickerController(picker, pickedImage: image)
    }

    @objc func imagePickerController(_ picker: UIImagePickerController, pickedImage: UIImage?) {
    }
}

Volle probe

BaseViewController.Swift

import UIKit

class BaseViewController: UIViewController {

    let imagePicker = UIImagePickerController()

    override func viewDidLoad() {
        super.viewDidLoad()
        imagePicker.delegate = self
    }
}
extension BaseViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

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

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        NSLog("\(info)")
        let image = info[UIImagePickerControllerOriginalImage] as? UIImage
        imagePickerController(picker, pickedImage: image)
    }

    @objc func imagePickerController(_ picker: UIImagePickerController, pickedImage: UIImage?) {
    }
}

ViewController.Swift

import UIKit

class ViewController: BaseViewController {

    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) {
        imagePicker.allowsEditing = false
        imagePicker.sourceType = .photoLibrary

        present(imagePicker, animated: true, completion: nil)
    }

    override func imagePickerController(_ picker: UIImagePickerController, pickedImage: UIImage?) {
        if let image = pickedImage {
            imageView?.image = image
            dismiss(animated: true, completion: nil)
        }
    }
}
9

Ich musste die Methodennamen direkt vom Delegierten kopieren. Aus irgendeinem Grund hat die automatische Vervollständigung die Methodenkopfzeilen falsch.

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)
}
5
Dustin Spengler

Sie müssen sicherstellen, dass UIImagePickerController nicht vor dem Aufruf des Delegaten freigegeben wurde.

Ich habe eine ImagePicker-Klasse erstellt, um alle UIImagePickerController-Elemente Zu verarbeiten.

Ich habe eine ähnliche Klasse erstellt, aber

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

funktionierte nicht für mich. 'picker' wurde veröffentlicht, bevor 'handler' aufgerufen werden konnte.

Ich habe eine permanente Referenz erstellt und es hat funktioniert:

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
Victor_Z

Ich habe dieses Problem auch angegangen und es mit der folgenden Lösung gelöst. Stellvertretervertreter nach der aktuellen Fertigstellung einstellen.

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

Hoffe das wird für dich funktionieren !!

2
iDev750

Ich fand, dass der Delegate-Code in einem aktiven UIViewController sein musste.

Ich habe ursprünglich versucht, meinen Code in einer separaten Datei zu speichern, beispielsweise als NSObject mit den korrekten Delegatenprotokollen wie folgt:

class PhotoPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

Das nannte die Delegiertenmethode jedoch nie.

Den genauen gleichen Code zu nehmen und ihn in den UIViewController zu setzen, nannte ich ihn aus, damit er funktioniert.

Es scheint, dass die beste Lösung die Erstellung einer Popup-Ansicht ist und der Code von ViewController aufbewahrt wird.

1
Nico teWinkel

Ich habe für diesen Artikel gestimmt, weil ich die UINavgationControllerDelegate -Deklaration verpasst habe und dieser Kommentar hat geholfen.

imagePickerController wurde nicht aufgerufen.

0
Eric Stevenson

Dieser Code funktioniert (obwohl er immer wieder neu angezeigt wird, weil er die Auswahl in viewWillAppear anzeigt, dies ist nur, um Code klein zu halten). Ich würde sehen, was anders ist. Könnte es mit Ihrem Top-View-Controller zu tun haben? Warum wird der Picker nicht einfach von einem View-Controller angezeigt, anstatt zum Top-View-Controller der Anwendung zu wechseln? Sobald Sie den Delegaten-Callback erhalten, müssen Sie den View-Controller schließen.

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