UIImagePickerController委托不叫Swift 3

表面上,我认为这必须是一个委托问题,但在询问委托人后,返回了正确的委托人。

我创build了一个ImagePicker类来处理所有的UIImagePickerController的东西。 每件事情都有效,直到委托方法需要被调用。 在我select一张照片后,imagePickerclosures,但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 } 

样品1

ViewController.swift

 import UIKit class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { @IBOutlet var imageView: UIImageView! let imagePicker = UIImagePickerController() @IBAction func showImages(_ sender: AnyObject) { imagePicker.allowsEditing = false imagePicker.sourceType = .photoLibrary present(imagePicker, animated: true, completion: nil) } override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self } // MARK: - UIImagePickerControllerDelegate Methods private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage { imageView.contentMode = .scaleAspectFit imageView.image = pickedImage } dismiss(animated: true, completion: nil) } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { NSLog("\(info)") if let image = info[UIImagePickerControllerOriginalImage] as? UIImage { imageView.image = image dismiss(animated: true, completion: nil) } } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil) } } 

Main.storyboard

 <?xml version="1.0" encoding="UTF-8" standalone="no"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <dependencies> <deployment identifier="iOS"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="tne-QT-ifu"> <objects> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_39682915" customModuleProvider="target" sceneMemberID="viewController"> <layoutGuides> <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> </layoutGuides> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="5hu-uL-xYz"> <constraints> <constraint firstAttribute="height" constant="128" id="pCf-Ho-iML"/> <constraint firstAttribute="width" constant="240" id="z83-As-vaM"/> </constraints> </imageView> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tya-gj-dk3"> <state key="normal" title="Button"/> <connections> <action selector="showImages:" destination="BYZ-38-t0r" eventType="touchUpInside" id="hfy-Gs-ly4"/> </connections> </button> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="5hu-uL-xYz" firstAttribute="centerX" secondItem="tya-gj-dk3" secondAttribute="centerX" id="axg-dI-kbi"/> <constraint firstItem="tya-gj-dk3" firstAttribute="top" secondItem="5hu-uL-xYz" secondAttribute="bottom" constant="8" symbolic="YES" id="mVi-bd-jbw"/> <constraint firstItem="5hu-uL-xYz" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="nvT-S1-cwf"/> <constraint firstItem="5hu-uL-xYz" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="qeA-tM-hB3"/> </constraints> </view> <connections> <outlet property="imageView" destination="5hu-uL-xYz" id="k3K-vo-bTE"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> </scene> </scenes> </document> 

的Info.plist

添加键/值NSPhotoLibraryUsageDescription = testingimagePicker

或添加代码

 <key>NSPhotoLibraryUsageDescription</key> <string>Test images</string> 

样品2

代码与inheritance。 您可以inheritanceBaseViewController类以使用已定义的UIImagePickerController创build新的UIViewController类

BaseViewController.swift

 import UIKit class BaseViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { let imagePicker = UIImagePickerController() override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self } 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) } func imagePickerController(_ picker: UIImagePickerController, pickedImage: UIImage?) { } } 

ViewController.swift

 import UIKit class ViewController: BaseViewController { @IBOutlet var imageView: UIImageView! @IBAction func showImages(_ sender: AnyObject) { imagePicker.allowsEditing = false imagePicker.sourceType = .photoLibrary present(imagePicker, animated: true, completion: nil) } override func viewDidLoad() { super.viewDidLoad() } override func imagePickerController(_ picker: UIImagePickerController, pickedImage: UIImage?) { if let image = pickedImage { imageView.image = image dismiss(animated: true, completion: nil) } } } 

我不得不直接从委托中复制方法名称。 出于某种原因,自动完成的方法标题是错误的。

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

哟必须确保UIImagePickerController没有被释放之前委托调用。

我创build了一个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'被调用之前被释放。

我创build了永久引用,它的工作原理:

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

这个代码可以工作,(但是,它会一遍又一遍地重新显示,因为它在viewWillAppear中显示select器,这只是为了保持代码小)。 我会看看与此不同的是什么。 它可能必须做你的顶级视图控制器? 为什么不直接从视图控制器显示select器,而不是去应用程序的顶部视图控制器? 此外,一旦你得到委托callback,你需要closures视图控制器。

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

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

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

 class PhotoPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate { 

但是,从来没有调用委托方法。

采取完全相同的代码,并把它放在UIViewController我叫它使其工作。

看起来最好的解决scheme是创build一个popup式视图,并使其ViewController保留代码。