首页 > 解决方案 > Swift 在将图像传递给另一个 ViewController 时打开 Optional 值时意外发现 nil

问题描述

我有两个 VC。第一个包含来自画廊的 imagePicker 和一个将图像发送到 chatLog 的回调函数......我想将选定的照片发送到第二个 VC

if let selectedImage = selectedImageFromPicker {

        //self.callback?(selectedImage)
        detailImageViewController.aImage = selectedImage
}

我创建了第二个 VC 作为 PreviewImage 的控制器,带有取消接受按钮。我试图以这种方式将第二个 VC 上显示的图像传递回第一个 VC,但它向我显示:

致命错误:在展开 Optional 值时意外发现 nil。

我该如何解决?

var t : EVTPhotoTekingHelper!

@objc func actionSend() {

    if aImage != nil{
        t.callback?(aImage!)
    }
    else {
        print("nil")
    }

    dismiss(animated: true, completion: nil)
}

更新:

我的第一个 VC

typealias PhotoTekingHelperCallBack = (UIImage?) -> ()

class EVTPhotoTekingHelper: NSObject {

// View controller on which AlertViewController and UIImageViewController are present
weak var viewController: UIViewController!

var imagePickerController: UIImagePickerController?
var callback: PhotoTekingHelperCallBack?
var photoTakinHelper: EVTPhotoTekingHelper!

// MARK: - Initialization

init(viewController: UIViewController, callback: @escaping PhotoTekingHelperCallBack) {

    self.viewController = viewController
    self.callback = callback

    super.init()

    showPhotoSourceSelection()
}

func showPhotoSourceSelection() {

    let alertController = UIAlertController.init(title: nil,
                                                 message: "Message?",
                                                 preferredStyle: .actionSheet)

    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    let photoLibraryAction = UIAlertAction(title: "from library", style: .default) { (action) in

        self.showImagePickerController(sourceType: .photoLibrary)

    }

    alertController.addAction(cancelAction)
    alertController.addAction(photoLibraryAction)


    if UIImagePickerController.isFlashAvailable(for: .rear) {

        let cameraAction = UIAlertAction.init(title: "from camera", style: .default, handler: { (action) in

            self.showImagePickerController(sourceType: .camera)
        })

        alertController.addAction(cameraAction)
    }

    viewController.present(alertController, animated: true, completion: nil)
}

func showImagePickerController(sourceType: UIImagePickerControllerSourceType) {

    imagePickerController = UIImagePickerController.init()
    imagePickerController!.sourceType = sourceType
    imagePickerController!.delegate = self

    viewController.present(imagePickerController!, animated: true, completion: nil)
}
}

从第一个 VC 扩展

extension EVTPhotoTekingHelper: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {


    var selectedImageFromPicker: UIImage?

    if let editedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
        selectedImageFromPicker = editedImage
    } else if let originImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
        selectedImageFromPicker = originImage
    }

    let detailImageViewController = EVImagePreviewController()
    let ncDetailImageViewController = UINavigationController(rootViewController: detailImageViewController)
    if let selectedImage = selectedImageFromPicker {

        //self.callback?(selectedImage)
        detailImageViewController.aImage = selectedImage
    }
    viewController.dismiss(animated: false, completion: nil)
    viewController.parent?.present(ncDetailImageViewController, animated: true, completion: nil)

}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
    viewController.dismiss(animated: false, completion: nil)
}
}

我的第二个 VC

class EVImagePreviewController: UIViewController, UIScrollViewDelegate {

var t : EVTPhotoTekingHelper!
var aImageView: UIImageView!
var aImage: UIImage!

private var aScrollView: UIScrollView!

override func viewDidAppear(_ animated: Bool) {


    aImageView = UIImageView(frame: CGRect(x: 0, y: 75, width: (aImage?.size.width)!, height: (aImage?.size.height)!))
    aImageView.contentMode = .scaleAspectFit
    aImageView.image = aImage

    aScrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
    aScrollView.backgroundColor = .clear
    aScrollView.contentSize = CGSize(width: view.frame.size.width, height: view.frame.height)
    aScrollView.minimumZoomScale  = 0.2
    aScrollView.maximumZoomScale  = 2.3
    aScrollView.clipsToBounds     = true
    aScrollView.delegate = self

    aScrollView.addSubview(aImageView)

    view.addSubview(aScrollView)

    aImageView.center = CGPoint(x: aScrollView.bounds.midX, y: aScrollView.bounds.midY - 35)
}

override func viewDidLoad() {
    super.viewDidLoad()

    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add", style: .plain, target: self, action: #selector(actionSend))
    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(actionBack))

}

// MARK: - IBAction

@objc func actionBack() {

    dismiss(animated: false, completion: nil)
}

@objc func actionSend() {

    print("\(t)")
    if aImage != nil{
        t.callback?(aImage!)
    }
    else {
        print("nil")
    }


    //self.callback?(aImage)
    dismiss(animated: true, completion: nil)
}

// MARK: - UIScrollViewDelegate

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return aImageView
}

func scrollViewDidZoom(_ scrollView: UIScrollView) {

    let subView = scrollView.subviews[0]

    let offsetX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0.0)
    let offsetY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0.0)

    subView.center = CGPoint(x: scrollView.contentSize.width * 0.5 + offsetX, y: scrollView.contentSize.height * 0.5 + offsetY)
}
}

标签: swiftimagepicker

解决方案


在这里,您在从第一个视图控制器的父级展示您的第二个视图控制器之前关闭您的第一个视图控制器:

viewController.dismiss(animated: false, completion: nil)

对我来说到目前为止没有任何意义。目前尚不清楚回调实现在哪里。

我猜测 nil 异常肯定不适用于 UIImage 。它在你的回调实现中的某个地方。


推荐阅读