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
}
Xcode 9.2, Swift 4
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?) {
}
}
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)
}
}
}
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)
}
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!)
}
})
....
}
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 !!
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.
Ich habe für diesen Artikel gestimmt, weil ich die UINavgationControllerDelegate
-Deklaration verpasst habe und dieser Kommentar hat geholfen.
imagePickerController
wurde nicht aufgerufen.
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)
}
}