在 iOS10 中使用 AVCapturePhotoOutput - NSGenericException

Posted

技术标签:

【中文标题】在 iOS10 中使用 AVCapturePhotoOutput - NSGenericException【英文标题】:Using AVCapturePhotoOutput in iOS10 - NSGenericException 【发布时间】:2017-03-28 01:47:48 【问题描述】:

我目前正在尝试弄清楚如何使用 ios 10 的 AVCapturePhotoOutput 方法,但在这样做时遇到了麻烦。我觉得我即将做对,但继续收到错误:

由于未捕获的异常“NSGenericException”而终止应用程序,原因:“-[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] 没有活动和启用的视频连接”

我尝试将这行代码放在 AVCapturePhotoCaptureDelegate 或我的 didPressTakePhoto 函数中:

if let videoConnection = stillImageOutput.connection(withMediaType: AVMediaTypeVideo) 
     videoConnection.videoOrientation = AVCaptureVideoOrientation.portrait;
     ...

这是我目前的代码:

import AVFoundation
import UIKit

class Camera: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, AVCapturePhotoCaptureDelegate 

    @IBOutlet weak var cameraView: UIView!
    @IBOutlet weak var imageView: UIImageView!

    var captureSession : AVCaptureSession?
    var stillImageOutput : AVCapturePhotoOutput?
    var stillImageOutputSettings : AVCapturePhotoSettings?
    var previewLayer : AVCaptureVideoPreviewLayer?

    var didTakePhoto = Bool();

    override func viewDidLoad() 
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    

    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated);

        previewLayer?.frame = cameraView.bounds;
    

    override func viewWillAppear(_ animated: Bool) 
        super.viewWillAppear(animated);

        captureSession = AVCaptureSession();
        captureSession?.sessionPreset = AVCaptureSessionPreset1920x1080;

        stillImageOutput = AVCapturePhotoOutput();

        let backCamera = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo);

        do 
            let input = try AVCaptureDeviceInput(device: backCamera)

            if (captureSession?.canAddInput(input))! 
                captureSession?.addInput(input);

                if (captureSession?.canAddOutput(stillImageOutput))! 
                    captureSession?.canAddOutput(stillImageOutput);

                    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
                    previewLayer?.videoGravity = AVLayerVideoGravityResizeAspect;
                    previewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.portrait;
                    cameraView.layer.addSublayer(previewLayer!);
                    captureSession?.startRunning();
                
            
         catch 
            print(error);
        
    

    func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) 
        if let error = error 
            print(error.localizedDescription);
        

        if let sampleBuffer = photoSampleBuffer, let previewBuffer = previewPhotoSampleBuffer, let dataImage = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewBuffer) 
            print(UIImage(data: dataImage)?.size as Any);

            let dataProvider = CGDataProvider(data: dataImage as CFData);
            let cgImageRef: CGImage! = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent);
            let image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: UIImageOrientation.right);

            self.imageView.image = image;
            self.imageView.isHidden = false;
        
    

    func didPressTakePhoto() 
            stillImageOutputSettings = AVCapturePhotoSettings();

            let previewPixelType = stillImageOutputSettings?.availablePreviewPhotoPixelFormatTypes.first!;
            let previewFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
                                 kCVPixelBufferWidthKey as String: 160,
                                 kCVPixelBufferHeightKey as String: 160];
            stillImageOutputSettings?.previewPhotoFormat = previewFormat;

            stillImageOutput.capturePhoto(with: stillImageOutputSettings!, delegate: self);
    

    func didPressTakeAnother() 
        if (didTakePhoto == true) 
            imageView.isHidden = true;
            didTakePhoto = false;
         else 
            captureSession?.startRunning();
            didTakePhoto = true;
            didPressTakePhoto();
        
    

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
        didPressTakeAnother();
    

有什么建议吗?

提前致谢!

【问题讨论】:

你是在模拟器上运行这个吗? 不,在我的 iPhone 6S+ 上运行它 【参考方案1】:

代码错误。

应该是这样的

if (captureSession?.canAddOutput(stillImageOutput))!
      captureSession?.addOutput(stillImageOutput)

【讨论】:

【参考方案2】:

对于其他可能试图弄清楚这一点的人,以下资源帮助了我:

供参考和代码布局

SnapChat: Camera 1

SnapChat: Camera 2

iOS10相机新功能的实际实现和使用

AV Foundation: iOS 10

iOS Custom Camera

【讨论】:

【参考方案3】:

AVCaptureSessionPreset1920x1080 更改为AVCaptureSessionPresetHigh

试试看

【讨论】:

以上是关于在 iOS10 中使用 AVCapturePhotoOutput - NSGenericException的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 10 中使用 UNNotificationSettings 检查通知类型

应用程序在 iOS 9 中崩溃,但在 iOS 10 中没有

如何在 iOS 10 或更低版本中使用 webview? [复制]

在 iOS10 中使用 AVCapturePhotoOutput - NSGenericException

使用 ios 10 Safari 浏览器在 ionic 中无法使用 Focus()

不推荐使用 setStatusBarOrientation,如何在 ios10 中更改设备方向