使用委托:在展开可选值时意外发现 nil

Posted

技术标签:

【中文标题】使用委托:在展开可选值时意外发现 nil【英文标题】:Using delegates: unexpectedly found nil while unwrapping an Optional value 【发布时间】:2015-05-30 16:02:54 【问题描述】:

我有两个ViewControllers,假设一个名为MainVC,另一个名为GetCameraRollImageViewController。在第二个中,有一个UIScrollView 包含一个UIImageView,因为我使用segue 来显示第二个视图控制器,所以我必须在MainVC 中使用它的委托:

class ViewController: UIViewController, GetTextDelegate, GetCameraRollImageDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate  
//
//other codes
//
    @IBAction func setNewImageFromCameraRoll(segue:UIStoryboardSegue)    
        if let newImageVC = segue.sourceViewController as? GetCameraRollImageViewController

            var scale:CGFloat = 1.0/newImageVC.scrollView.zoomScale;
            var visibleRect:CGRect!
            visibleRect.origin.x = newImageVC.scrollView.contentOffset.x * scale;
            visibleRect.origin.y = newImageVC.scrollView.contentOffset.y * scale;
            visibleRect.size.width = newImageVC.scrollView.bounds.size.width * scale;
            visibleRect.size.height = newImageVC.scrollView.bounds.size.height * scale;
            var cr:CGImageRef = CGImageCreateWithImageInRect(newImageVC.inputImage.image?.CGImage,visibleRect)
            var cropped:UIImage = UIImage(CGImage: cr)!
            imageView.image = cropped
        
    

GetCameraRollImageViewController 代码:

import UIKit

protocol GetCameraRollImageDelegate
    //


class GetCameraRollImageViewController: UIViewController, UIScrollViewDelegate 

    var delegate:GetCameraRollImageDelegate? = nil
    var inputImageDelegate:UIImage!

    @IBOutlet var scrollView: UIScrollView!
    @IBOutlet var inputImage:UIImageView!

    override func viewDidLoad() 
        super.viewDidLoad()
        self.scrollView.minimumZoomScale = 0.5
        self.scrollView.maximumZoomScale = 6.0
        self.scrollView.contentSize = self.inputImage.frame.size;
        self.scrollView.delegate = self
        inputImage.image = inputImageDelegate

    func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? 
        return self.inputImage
    


但是当我触发 setNewImageFromCameraRoll() 时,应用程序会因以下错误而崩溃:

fatal error: unexpectedly found nil while unwrapping an Optional value

注意scrollViewinputImage 是有界的,当它们为空时,我不会在 viewDidLoad() 中读取它们。

【问题讨论】:

fatal error: unexpectedly found nil while unwrapping an Optional value in Swift的可能重复 @GoZoner 它没有重复,因为 1)我没有在 ViewDidLoad() 中阅读 2)我正在使用 if ..let 【参考方案1】:

我不是 100%,但我相信您的问题是 scrollView 尚未创建。尝试将图像传递给新的视图控制器并在 GetCameraRollImageViewController 的 viewDidLoad 中调整大小。

【讨论】:

【参考方案2】:

你的代码有很多问题。

首先,为什么会有一个以segue为参数的IBAction?

通常你所做的就是通过任何方法调用一个 segue,然后实现 preformSegue 方法。每当在视图控制器中触发 segue 时,就会调用该方法。

在 performSegue 中,您可以获得指向目标视图控制器的指针并将参数传递给它。

我不清楚你的 setNewImageFromCameraRoll 方法是如何被调用的,或者它是如何获得一个 segue 对象的。您使用 segue 中的 source 视图控制器对我来说也没有意义。我怀疑该方法没有按您的预期工作。

下一个问题与您尝试对从 segue 获得的视图控制器执行的操作有关。您正在尝试直接操纵它的视图。不要那样做。您应该将视图控制器的视图视为私有视图。相反,您应该向视图控制器添加属性以公开您需要的信息,并引用这些属性。

弄乱另一个视图控制器的视图违反了封装原则。它也经常失败,因为其他视图控制器的视图在它显示在屏幕上之前不会被创建。

【讨论】:

感谢您的回复。这是您的第一个问题answer。对于第二个问题,我不直接操作该视图,我只是在读取一些值。 哦,放松的转场!好的,这就解释了。我没怎么用过。 读取值和写入值一样糟糕,而且很可能会失败。您应该将另一个视图控制器的视图视为私有视图,并添加属性以将信息公开到 VC 的公共接口。【参考方案3】:

据我所知,您尚未在 MainVC 中将 V2 类的委托连接到自身 "newImageVC?.delegate=self"

【讨论】:

【参考方案4】:

[根据cmets更新]

线

var visibleRect:CGRect!

visibleRect 分配给nil,因此是

visibleRect.origin.x = newImageVC.scrollView.contentOffset.x * scale;

然后将取消引用visibleRect,找到nil 并产生异常。您需要分配一个CGRect 并将其分配给visibleRect

[原答案]

visibleRect 绑定了吗?看起来不像。如果这是绑定的,那么您会注意到 ! 的其他用途...您需要绑定您的插座(通常在 InterfaceBuilder 中):

@IBOutlet var scrollView: UIScrollView!
@IBOutlet var inputImage:UIImageView!

也许scrollView 没有绑定,因此,因为它被隐式解包(! 运算符),当您将其引用为nil 时,您的程序将是致命的。

用途:

var visibleRect = 
  CGRectMake (newImageVC.scrollView.contentOffset.x * scale,
              newImageVC.scrollView.contentOffset.y * scale,
              newImageVC.scrollView.bounds.size.width * scale,
              newImageVC.scrollView.bounds.size.height * scale)

【讨论】:

它在 IB 中是有界的。 这是一个局部变量 var visibleRect = CGRectMake(...)。当你写 var visibleRect:CGRect! 时,visibleRect 就是 nil 并且 失败。在您的代码中,您只声明了它的类型,但没有为它分配任何内存。 而且你最好在给它赋值之前先分配它。 谢谢,这就是问题所在!

以上是关于使用委托:在展开可选值时意外发现 nil的主要内容,如果未能解决你的问题,请参考以下文章

在 SWIFT 3.0 中展开可选值时意外发现 nil

致命错误:在展开可选值时意外发现 nil - 当 UITextField 被点击时

Alamofire:在展开可选值时意外发现 nil

prepareForSegue 出错“”在展开可选值时意外发现 nil“”

UIPickerView:在展开可选值时意外发现 nil

致命错误:在展开可选值时意外发现 nil - 为啥?