Swift &引用;在展开可选值“时意外发现nil”;内置captureOutput函数

Swift &引用;在展开可选值“时意外发现nil”;内置captureOutput函数,swift,optional,capture-output,Swift,Optional,Capture Output,我有一个函数可以旋转UIImages上的色调,这些图像来自同一类中的其他函数,但在captureOutput函数(与AVCaptureVideoDataOutput一起使用)中,同一图像对象会使我的应用程序崩溃,并显示“在展开可选值时意外发现零”。我对它的调用方式似乎没有什么不同,所以它可能与captureOutput函数及其允许的功能有关 在viewController类声明之外: var image:UIImage? = nil var imageSource:UIImage? = nil

我有一个函数可以旋转UIImages上的色调,这些图像来自同一类中的其他函数,但在captureOutput函数(与AVCaptureVideoDataOutput一起使用)中,同一图像对象会使我的应用程序崩溃,并显示“在展开可选值时意外发现零”。我对它的调用方式似乎没有什么不同,所以它可能与captureOutput函数及其允许的功能有关

在viewController类声明之外:

var image:UIImage? = nil
var imageSource:UIImage? = nil
var imageView:UIImageView? = nil;
var hueDeg:CGFloat = 0.00
职能:

func rotateHue(with source: UIImage, rotatedByHue deltaHueRadians: CGFloat) -> UIImage {
    // Create a Core Image version of the image.
    let sourceCore = CIImage(cgImage: (source.cgImage)!) // crashes here
    // Apply a CIHueAdjust filter
    let hueAdjust = CIFilter(name: "CIHueAdjust")
    hueAdjust?.setDefaults()
    hueAdjust?.setValue(sourceCore, forKey: "inputImage")
    hueAdjust?.setValue(deltaHueRadians, forKey: "inputAngle")
    let resultCore = hueAdjust?.value(forKey: "outputImage") as? CIImage
    // Convert the filter output back into a UIImage.
    let context = CIContext(options: nil)
    let resultRef = context.createCGImage(resultCore!, from: (resultCore?.extent)!)
    let result = UIImage(cgImage: resultRef!)
    //CGImageRelease(resultRef)
    return result
}

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection){
    let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    let cameraImage = CIImage(cvPixelBuffer: pixelBuffer!)

    image = UIImage(ciImage: cameraImage)

    image = rotateHue(with:image!, rotatedByHue:hueDeg) 

    DispatchQueue.main.async(){

        imageView!.image = image
    }

}
这是我调用rotateHue的另一个函数,它不会崩溃。这是一个由计时器调用的函数:

@objc func cycleHue(){
    hueDeg += 0.2;
    image = imageSource
    image = rotateHue(with:image!, rotatedByHue:hueDeg)
    imageView!.image = UIImage(cgImage: (image?.cgImage)!, scale: 1.0, orientation: UIImageOrientation.right)
}

UIImage
cgImage
属性的文档说明如下:

如果UIImage对象是使用CIImage对象初始化的,则该属性的值为NULL

由于此值可以是
nil
,因此不应使用强制展开(
)操作符,否则可能会发生崩溃,正如您所看到的那样。相反,我们需要测试该值可能为
nil
的条件

幸运的是,使
cgImage
变为
nil
的条件是它显然是使用
CIImage
初始化的。既然你想要的是
CIImage
,那么正确的方法就是:

  • 调用
    UIImage
    ciImage
    属性,如果得到非nil值,则使用该属性
  • 如果
    ciImage
    nil
    ,则返回调用
    cgImage
    并在其为非
    nil
    时从中生成
    ciImage
  • 如果
    cgImage
    恰好也为零,则发生了一些奇怪的事情;在这种情况下,您可以抛出错误或以其他方式优雅地退出

  • UIImage
    cgImage
    属性的文档说明如下:

    如果UIImage对象是使用CIImage对象初始化的,则该属性的值为NULL

    由于此值可以是
    nil
    ,因此不应使用强制展开(
    )操作符,否则可能会发生崩溃,正如您所看到的那样。相反,我们需要测试该值可能为
    nil
    的条件

    幸运的是,使
    cgImage
    变为
    nil
    的条件是它显然是使用
    CIImage
    初始化的。既然你想要的是
    CIImage
    ,那么正确的方法就是:

  • 调用
    UIImage
    ciImage
    属性,如果得到非nil值,则使用该属性
  • 如果
    ciImage
    nil
    ,则返回调用
    cgImage
    并在其为非
    nil
    时从中生成
    ciImage
  • 如果
    cgImage
    恰好也为零,则发生了一些奇怪的事情;在这种情况下,您可以抛出错误或以其他方式优雅地退出

  • 崩溃时哪个值为零?这是你的第一条线索。如果可能的话,你应该避免使用强制展开(
    )。始终使用
    if let
    guard let
    安全地打开包装。我以为它会是“图像”,但如果我去掉rotateHue的函数调用,它不会崩溃,并在应用程序上显示相机输出。在rotateHue()中分配sourceCore时发生。崩溃时哪个值为零?这是你的第一条线索。如果可能的话,你应该避免使用强制展开(
    )。始终使用
    if let
    guard let
    安全地打开包装。我以为它会是“图像”,但如果我去掉rotateHue的函数调用,它不会崩溃,并在应用程序上显示相机输出。在rotateHue()中分配sourceCore时发生。UIImage的ciImage似乎是非nil的,它调用函数并以相同的方式崩溃:if(image?.ciImage!=nil)image=rotateHue(with:image!,rotatedByHue:hueDeg)@这说明只要
    image
    为nil,就会崩溃。不要用力展开。如果let或
    保护let
    则使用
    。@同样,也不要测试
    image?.ciImage!=nil
    ,如果让ciImage=image?.ciImage
    执行类似于
    的操作,然后使用生成的
    ciImage
    。我建议更改
    rotateHue
    的签名以获取
    CIImage
    而不是
    UIImage
    ,然后将从
    if let
    中获得的值传递给它。UIImage的CIImage似乎不是nil,它调用函数并以相同的方式崩溃:if(image?.CIImage!=nil)image=rotateHue(使用:image!,按色调:hueDeg旋转)@模糊解释:当
    image
    为零时,一个将崩溃。不要使用强制展开。如果let
    保护let
    则使用
    。@模糊解释也不是测试
    image?.ciImage!=nil
    ,你应该做类似
    的事情,如果let ciImage=image?.ciImage
    ,然后使用结果使用
    CIImage
    。我建议将
    rotateHue
    的签名更改为使用
    CIImage
    而不是
    UIImage
    ,然后将从
    中获得的值传递给它(如果让
    )。