如何将捕获的照片转换为主线程?

时间:2016-06-08 23:05:14

标签: ios swift grand-central-dispatch avcapturesession

我有一个通过captureStillImageAsynchronouslyFromConnection() - 方法用相机拍摄照片的功能。 捕获的图像是我capture() - 方法的返回值。

我想将捕获的照片保存到我的ViewController中的变量中,然后执行segue到另一个ViewController,它将显示照片。这似乎不起作用,我得到fatal error: unexpectedly found nil while unwrapping an Optional value - 错误。

我知道这是因为var photo: UIImage!nil,但在调用performSegue...函数之前如何将照片数据放入主线程?

我的照片功能(在我的CameraSession-Class中)和会话队列:

var sessionQueue = dispatch_queue_create("CameraSession", DISPATCH_QUEUE_SERIAL) 

func capture(saveToGallery save: Bool) -> UIImage {
    var capturedImage = UIImage()

    let connection = self.output.connectionWithMediaType(AVMediaTypeVideo)
    connection.videoOrientation = .Portrait

    dispatch_async(sessionQueue, {
        self.output.captureStillImageAsynchronouslyFromConnection(
            connection, completionHandler: {
                (imageDataSampleBuffer: CMSampleBuffer?, error: NSError?) -> Void in
                if imageDataSampleBuffer != nil {
                    let imageData: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
                         self.capturedImage = UIImage(data: imageData)

                    if save {
                        UIImageWriteToSavedPhotosAlbum(self.capturedImage!, nil, nil, nil)
                    }
                }
            }
        )
    })

    return self.capturedImage!
}

我在ViewController-Class中的函数:

func capture() {
    let photo = cameraSession.capture(saveToGallery: true)
    performSegueWithIdentifier("showPhoto", sender: self) // This will switch to another ViewController, which shows the captured photo.
}

3 个答案:

答案 0 :(得分:0)

由于您正在异步捕捉照片,因此您的功能将会到达

return self.capturedImage!
拍摄照片之前

,并且self.capturedImage为零。在图像数据返回后,您应该移动处理segue的逻辑。通过将回调添加为捕获方法的参数,这可能是最容易实现的:

func capture(saveToGallery save: Bool, callback:UIImage -> Void) -> Void

然后不是直接返回UIImage,而是将其作为参数传递给你的回调:

let imageData: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
    self.capturedImage = UIImage(data: imageData)

if save {
    UIImageWriteToSavedPhotosAlbum(self.capturedImage!, nil, nil, nil)
}

callback(self.capturedImage)

你的UIViewController捕获方法看起来像:

func capture() {
    let photo = cameraSession.capture(saveToGallery: true, callback: {
    (photo: UIImage) -> Void in
    //save your photo locally in your UIViewController class here if you need to
    performSegueWithIdentifier("showPhoto", sender: self)
    })
}

答案 1 :(得分:0)

将捕获(:_)方法作为第二个参数传递给UIImage。当您创建捕获的图像时,在保存后,调用与图像一起传递的块。在调用之前,只需将其调度到主队列即可。然后你会有更多的东西:

func capture() {
    cameraSession.capture(saveToGallery: true) {
        [unowned self] image in
        self.myCapturedImage = image
        self.performSegueWithIdentifier("showPhoto", sender: self)
    }
}

答案 2 :(得分:0)

您可以像这样请求主(UI)线程:

dispatch_async(dispatch_get_main_queue(), ^{
    //Do something in main thread
});