图像选择器控制器代表在单独的类中不起作用

时间:2017-07-19 23:54:00

标签: ios swift uiimagepickercontroller

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

到目前为止一切正常,除了一件事。本教程处理主ViewController类中的Image Picker委托,使其符合UIImagePickerControllerDelegateUINavigationControllerDelegate协议。我想尝试别的东西并将委托移到单独的类。这就是我的所作所为:

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错误:(null)返回0宽度,假设UIViewNoIntrinsicMetric

我做错了什么? UIViewController是否可以选择代表的超类?我觉得可能不是。

1 个答案:

答案 0 :(得分:2)

您的问题是内存管理问题。在selectImageFromPhotoLibrary内,您可以创建MealPhotoDelegate的本地实例。在方法结束时,此实例超出范围并被取消分配,因为没有强引用。因此,图片选择器的代理人变为nil,但它无法正常工作。

解决方案是强烈引用MealPhotoDelegate的实例。使用视图控制器类中的属性可以轻松完成此操作。

将以下属性添加到视图控制器类:

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