En apparence, j’ai pensé que c’était un problème de délégué, mais après avoir demandé au délégué, le droit était renvoyé.
J'ai créé une classe ImagePicker pour gérer tout le matériel UIImagePickerController. Tout fonctionne jusqu'à ce que les méthodes déléguées doivent être appelées. Une fois que j'ai choisi une photo, imagePicker est rejeté, mais la méthode didFinishPickingMediaWithInfo
n'est jamais appelée. S'il vous plaît aider! Merci :)
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)
}
}
Cela ne s'appelle jamais:
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)
}
}
}
Je devais copier les noms de méthodes directement du délégué. Pour une raison quelconque, l'auto-complétion présente des en-têtes de méthode incorrects.
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)
}
Vous devez vous assurer que UIImagePickerController n'a pas été publié avant que le délégué appelle.
J'ai créé une classe ImagePicker pour gérer tous les fichiers UIImagePickerController.
J'ai créé une classe similaire, mais
func onButtonDidTap(sender: UIButton) {
.....
let picker = VLImagePickerController()
picker.show(fromSender: sender, handler: { (image: UIImage?) -> (Void) in
if (image != nil) {
self.setImage(image!)
}
})
....
}
n'a pas fonctionné pour moi . 'picker' a été publié avant que 'handler' puisse être appelé.
J'ai créé une référence permanente, et cela a fonctionné:
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!)
}
})
....
}
J'ai également fait face à ce problème et résolu en utilisant la solution ci-dessous. Définir le délégué du préparateur après la fin du présent.
controller.present(picker, animated: true, completion: {
self.picker.delegate = self
})
J'espère que cela fonctionnera pour vous !!
J'ai trouvé que le code de délégué devait être dans un UIViewController actif.
Au départ, j'avais essayé de placer mon code dans un fichier séparé, tel que NSObject avec les protocoles de délégation corrects déclarés, comme ceci:
class PhotoPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
Mais cela n'a jamais appelé les méthodes de délégué.
Prendre le même code exact et le placer dans UIViewController dont je l’appelais l’a fait fonctionner.
Il semble que la meilleure solution consiste à créer une vue de type contextuelle et à laisser son ViewController conserver le code.
Ce code fonctionne (bien qu'il réapparaisse encore et encore car il affiche le sélecteur dans viewWillAppear, ceci est juste pour garder le code petit) Je regarderais ce qui est différent de cela. Cela pourrait avoir à voir avec votre contrôleur de vue supérieure? Pourquoi ne pas simplement afficher le sélecteur à partir d'un contrôleur de vue plutôt que d'accéder au contrôleur de vue supérieur de l'application? En outre, une fois que vous avez reçu le rappel du délégué, vous devez fermer le contrôleur de vue.
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)
}
}