单独 class 中的图像选择器控制器委托不起作用
Image Picker Controller delegate in separate class doesn't work
我是 Xcode 和 Swift 的新手。我目前正在研究 Apple 的 Start Developing iOS Apps (Swift) 教程。
到目前为止一切正常,除了一件事。本教程在主要 ViewController
class 中处理图像选择器委托,使其符合 UIImagePickerControllerDelegate
和 UINavigationControllerDelegate
协议。我想尝试其他方法并将委托移动到单独的 class。这是我所做的:
import UIKit
import Foundation
class MealPhotoDelegate: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var placeholder: UIImageView?
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
placeholder!.image = selectedImage
dismiss(animated: true, completion: nil)
}
}
并且在 ViewController
中:
@IBAction func selectImageFromPhotoLibrary(_ sender: UITapGestureRecognizer) {
nameTextField.resignFirstResponder()
let imagePickerController = UIImagePickerController()
imagePickerController.sourceType = .photoLibrary
let imagePickerDelegate = MealPhotoDelegate()
imagePickerDelegate.placeholder = photoImageView
imagePickerController.delegate = imagePickerDelegate
present(imagePickerController, animated: true, completion: nil)
}
每次出现图像选择器以及浏览照片时,都会生成错误:
2017-07-20 01:49:00.937470+0200 FoodTracker[41600:4236501] API error: (null) returned 0 width, assuming UIViewNoIntrinsicMetric
我做错了什么? UIViewController
superclass 是代表的好选择吗?我觉得可能不是。
您的问题之一是内存管理。在您的 selectImageFromPhotoLibrary
中,您创建了一个 MealPhotoDelegate
的本地实例。在方法结束时,这个实例超出范围并被释放,因为没有对它的强引用。因此,图像选择器的委托变为 nil
并且不起作用。
解决方法是对MealPhotoDelegate
的实例进行强引用。使用视图控制器 class.
中的 属性 可以轻松完成此操作
将以下 属性 添加到您的视图控制器 class:
var imagePickerDelegate: MealPhotoDelegate?
然后更新行:
let imagePickerDelegate = MealPhotoDelegate()
与:
imagePickerDelegate = MealPhotoDelegate()
就是这样。现在可以使用了。
附带说明一下,您的 MealPhotoDelegate
没有理由扩展 UIViewController
。改为扩展 NSObject
。您可以使用正确的代码解决新问题。
应该是这样的:
class MealPhotoDelegate: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var placeholder: UIImageView?
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
if let placeholder = placeholder {
placeholder.image = selectedImage
}
picker.dismiss(animated: true, completion: nil)
}
}
我是 Xcode 和 Swift 的新手。我目前正在研究 Apple 的 Start Developing iOS Apps (Swift) 教程。
到目前为止一切正常,除了一件事。本教程在主要 ViewController
class 中处理图像选择器委托,使其符合 UIImagePickerControllerDelegate
和 UINavigationControllerDelegate
协议。我想尝试其他方法并将委托移动到单独的 class。这是我所做的:
import UIKit
import Foundation
class MealPhotoDelegate: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var placeholder: UIImageView?
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
placeholder!.image = selectedImage
dismiss(animated: true, completion: nil)
}
}
并且在 ViewController
中:
@IBAction func selectImageFromPhotoLibrary(_ sender: UITapGestureRecognizer) {
nameTextField.resignFirstResponder()
let imagePickerController = UIImagePickerController()
imagePickerController.sourceType = .photoLibrary
let imagePickerDelegate = MealPhotoDelegate()
imagePickerDelegate.placeholder = photoImageView
imagePickerController.delegate = imagePickerDelegate
present(imagePickerController, animated: true, completion: nil)
}
每次出现图像选择器以及浏览照片时,都会生成错误:
2017-07-20 01:49:00.937470+0200 FoodTracker[41600:4236501] API error: (null) returned 0 width, assuming UIViewNoIntrinsicMetric
我做错了什么? UIViewController
superclass 是代表的好选择吗?我觉得可能不是。
您的问题之一是内存管理。在您的 selectImageFromPhotoLibrary
中,您创建了一个 MealPhotoDelegate
的本地实例。在方法结束时,这个实例超出范围并被释放,因为没有对它的强引用。因此,图像选择器的委托变为 nil
并且不起作用。
解决方法是对MealPhotoDelegate
的实例进行强引用。使用视图控制器 class.
将以下 属性 添加到您的视图控制器 class:
var imagePickerDelegate: MealPhotoDelegate?
然后更新行:
let imagePickerDelegate = MealPhotoDelegate()
与:
imagePickerDelegate = MealPhotoDelegate()
就是这样。现在可以使用了。
附带说明一下,您的 MealPhotoDelegate
没有理由扩展 UIViewController
。改为扩展 NSObject
。您可以使用正确的代码解决新问题。
应该是这样的:
class MealPhotoDelegate: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var placeholder: UIImageView?
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
if let placeholder = placeholder {
placeholder.image = selectedImage
}
picker.dismiss(animated: true, completion: nil)
}
}