swift - 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)
}
}
解决方案
在这里,您在从第一个视图控制器的父级展示您的第二个视图控制器之前关闭您的第一个视图控制器:
viewController.dismiss(animated: false, completion: nil)
对我来说到目前为止没有任何意义。目前尚不清楚回调实现在哪里。
我猜测 nil 异常肯定不适用于 UIImage 。它在你的回调实现中的某个地方。
推荐阅读
- javascript - Discord.js 即使应用程序重新启动,也会在一定时间后执行某些操作
- python - 如何引用数据源的tableview?
- reactjs - TypeError: Object(...) is not a function with react-query
- javascript - 如何从多个调用特定的嵌套函数
- r - 按日期的情绪分析
- javascript - React 中的 setInterval() 和 clearInterval()
- python - 如何将 None 转换为 R NULL
- c - 在 c 中加载 glsl 时遇到问题
- jquery - 页面加载后将 CSS 添加到特定类
- mysql - 多个 id 的多 SELECT 查询