单独 class 中的图像选择器控制器委托不起作用

Image Picker Controller delegate in separate class doesn't work

我是 Xcode 和 Swift 的新手。我目前正在研究 Apple 的 Start Developing iOS Apps (Swift) 教程。

到目前为止一切正常,除了一件事。本教程在主要 ViewController class 中处理图像选择器委托,使其符合 UIImagePickerControllerDelegateUINavigationControllerDelegate 协议。我想尝试其他方法并将委托移动到单独的 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)
    }
}