ios - AVCaptureSession 崩溃

标签 ios swift

我正在使用该代码拍照 我能够尽可能快地拍照。 快速拍摄多张照片应用程序会崩溃。

我使用的是 Swift 1.1。

错误:

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“+[AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:] - 空样本缓冲区。'

 class ViewController: UIViewController {
    let captureSession = AVCaptureSession()
    var previewLayer : AVCaptureVideoPreviewLayer?
    var captureDevice : AVCaptureDevice?
    var captureConnection: AVCaptureConnection?
    var stillImageOutput = AVCaptureStillImageOutput()
    let targetRegion = CALayer()
    var currentImage: UIImage?

    @IBOutlet weak var cameraView: UIImageView!
    @IBOutlet weak var imageDisplayed: UIImageView!


    override func viewDidLoad() {
        super.viewDidLoad()

        navigationController?.setNavigationBarHidden(true, animated: true)

        captureSession.sessionPreset = AVCaptureSessionPreset1920x1080
        let devices = AVCaptureDevice.devices()
        for device in devices {
            if device.hasMediaType(AVMediaTypeVideo) {
                if device.position == AVCaptureDevicePosition.Back {
                    captureDevice = device as? AVCaptureDevice
                }
            }
        }
        if captureDevice != nil {
            println("Device trovato")
            beginSession()
        }


    }


    func beginSession() {

        var err: NSError? = nil
        captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err))

        if err != nil {
            println("err \(err?.localizedDescription)")
            return
        }

        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        self.view.layer.addSublayer(previewLayer)

        previewLayer?.frame = CGRect(x: cameraView.frame.origin.x, y: cameraView.frame.origin.y, width: cameraView.frame.size.width, height: cameraView.frame.size.height)

        captureSetup()
        captureSession.startRunning()
    }

    func captureSetup() {

        let outputSetting = NSDictionary(dictionary: [AVVideoCodecKey: AVVideoCodecJPEG])
        self.stillImageOutput.outputSettings = outputSetting
        self.captureSession.addOutput(stillImageOutput)
        for connection:AVCaptureConnection in self.stillImageOutput.connections as [AVCaptureConnection] {

            for port:AVCaptureInputPort in connection.inputPorts! as [AVCaptureInputPort] {
                if port.mediaType == AVMediaTypeVideo {
                    captureConnection = connection as AVCaptureConnection
                    break
                }
            }
            if captureConnection != nil {
                break
            }
        }
    }


    var i = 0;

    func captureScene() {


        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
            if self.captureConnection != nil {
                self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.captureConnection, completionHandler:{ (imageSampleBuffer:CMSampleBuffer!, _) -> Void in

                    let imageDataJpeg = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageSampleBuffer)
                    var pickedImage: UIImage = UIImage(data:imageDataJpeg)!



                    if let data = UIImagePNGRepresentation(pickedImage) {


                        let filename = self.getDocumentsDirectory().stringByAppendingPathComponent("\(self.i).png")
                        data.writeToFile(filename, atomically: true)

                        self.i++
                    }


                })
            }
        })

    }



    func getDocumentsDirectory() -> NSString {
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        let documentsDirectory: AnyObject = paths[0]


        return documentsDirectory as NSString
    }




    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        captureScene()
    }

}

最佳答案

@alper 在 linked answer 中解释的内容是有时 imageSampleBuffer 可以为 nil,这就是崩溃的根源。


我相信在 Swift 2 中 imageSampleBuffer 是可选的,因此为了避免这种崩溃,您可以检查 nil。示例:

if imageSampleBuffer != nil {
    let imageDataJpeg = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageSampleBuffer)
    // ...
} else {
    // handle or ignore the error
}

但是您使用的是 Swift 1,这是一个问题,因为在 Swift 1 中,imageSampleBuffer 被声明为隐式展开的可选值,这意味着它不能为 nil,您不能像在前面的例子。

@alper给出的解决方案是使用

CMSampleBufferIsValid(imageSampleBuffer)

作为检查缓冲区是否有效的一种方式。


如果前面的解决方案不起作用,您可以试试这个。

当我查看函数签名时:

self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.captureConnection, completionHandler:{ (imageSampleBuffer:CMSampleBuffer!, _) -> Void in

我看到缓冲区旁边还有另一个参数,但您忽略了它:

(imageSampleBuffer:CMSampleBuffer!, _)

我没有查找 Swift 1 文档,但如果 _ 实际上是一个错误参数,我不会感到惊讶。尝试用这样的 error 替换它:

self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.captureConnection, completionHandler:{ (imageSampleBuffer:CMSampleBuffer!, error) -> Void in

或者也许

self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.captureConnection, completionHandler:{ (imageSampleBuffer:CMSampleBuffer!, error:NSError) -> Void in

然后在继续 imageSampleBuffer 之前检查 error 的内容。

注意:正如我在最后一部分所说,错误 的解决方案是一个猜测,我没有测试:您必须尝试、适应并看看我的想法对不对。如果您能找到关于此的 Swift 1 文档并明确地告诉我们它,那将是理想的。


关于ios - AVCaptureSession 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34024942/

相关文章:

ios - 将 json 对象从 iphone 发送到 java servlet 的时间太长

ios - 尝试呈现 View Controller 时,对开始/结束外观转换的调用不平衡

ios - 如何将当前日期转换为特定的 24 小时格式?

ios - swift 3 : unrecognized selector sent to instance for gesture recognizer

arrays - 使用迭代器而不是 Swift 中的位置访问数组的元素

ios - NSNotification到达后,我无法编辑任何框架

ios - swift auto-abbreviates my NSURL with "... "over the characters it can't fit?

ios - 异步调用完成后如何启动另一个任务

ios - 更新 TableView 导致滞后和警告

ios - 如何过滤获取的数据并将其加载到 TableView 中?