为啥在 AVCapturePhotoOutput 上调用 .capturePhoto(with:,delegate:) 会导致崩溃
Posted
技术标签:
【中文标题】为啥在 AVCapturePhotoOutput 上调用 .capturePhoto(with:,delegate:) 会导致崩溃【英文标题】:Why does calling .capturePhoto(with:,delegate:) on AVCapturePhotoOutput cause a crash为什么在 AVCapturePhotoOutput 上调用 .capturePhoto(with:,delegate:) 会导致崩溃 【发布时间】:2018-02-16 23:56:34 【问题描述】:这几天我一直在为这个错误而苦苦挣扎,如果我拍摄画面连续屏幕,关闭当前屏幕翻转相机并拍照,应用程序会因错误而崩溃。
[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] 没有活动和启用的视频连接'
我已将错误缩小到三行代码,虽然我不知道如何修复它我相信解决方案与我的AVCapturePhotoSettings
有关
这是我将故障代码缩小到的地方:
@IBAction func cameraButton_TouchUpInside(_ sender: Any)
let settings = AVCapturePhotoSettings()
photoOutPut?.capturePhoto(with: settings, delegate: self as AVCapturePhotoCaptureDelegate)
我是否设置错误。谢谢
这是完整的代码
import UIKit
import AVFoundation
protocol previewSegueDelegate
func previewSegueDelegate(image:UIImage,device:AVCaptureDevice)
class MainCameraCollectionViewCell: UICollectionViewCell
var gdelegate: gestureDelegate?
var pdelegate: previewSegueDelegate?
@IBOutlet weak var myView: UIView!
var captureSession = AVCaptureSession()
private var sessionQueue: DispatchQueue!
var captureConnection = AVCaptureConnection()
var currentCamera: AVCaptureDevice?
var photoOutPut: AVCapturePhotoOutput?
var cameraPreviewLayer: AVCaptureVideoPreviewLayer?
var image: UIImage?
var usingFrontCamera = false
override func awakeFromNib()
super.awakeFromNib()
setupCaptureSession()
setupDevice()
setupInput()
setupPreviewLayer()
startRunningCaptureSession()
print("Inside of camera cell")
func setupCaptureSession()
captureSession.sessionPreset = AVCaptureSession.Preset.photo
sessionQueue = DispatchQueue(label: "session queue")
func setupDevice(usingFrontCamera:Bool = false)
sessionQueue.async
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified)
let devices = deviceDiscoverySession.devices
for device in devices
if usingFrontCamera && device.position == AVCaptureDevice.Position.front
self.currentCamera = device
else if device.position == AVCaptureDevice.Position.back
self.currentCamera = device
func setupInput()
sessionQueue.async
do
let captureDeviceInput = try AVCaptureDeviceInput(device: self.currentCamera!)
if self.captureSession.canAddInput(captureDeviceInput)
self.captureSession.addInput(captureDeviceInput)
self.photoOutPut = AVCapturePhotoOutput()
self.photoOutPut?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format:[AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
if self.captureSession.canAddOutput(self.photoOutPut!)
self.captureSession.addOutput(self.photoOutPut!)
catch
print(error)
func setupPreviewLayer()
cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
cameraPreviewLayer?.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
self.layer.insertSublayer(cameraPreviewLayer!, at: 0)
func startRunningCaptureSession()
captureSession.startRunning()
@IBAction func cameraButton_TouchUpInside(_ sender: Any)
let settings = AVCapturePhotoSettings()
photoOutPut?.capturePhoto(with: settings, delegate: self as AVCapturePhotoCaptureDelegate)
print("camera button touched")
@IBAction func FlipThe_camera(_ sender: UIButton)
print("Flip Touched")
captureSession.beginConfiguration()
if let inputs = captureSession.inputs as? [AVCaptureDeviceInput]
for input in inputs
captureSession.removeInput(input)
usingFrontCamera = !usingFrontCamera
setupCaptureSession()
setupDevice(usingFrontCamera: usingFrontCamera)
setupInput()
captureSession.commitConfiguration()
startRunningCaptureSession()
extension MainCameraCollectionViewCell: AVCapturePhotoCaptureDelegate
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)
if let imageData = photo.fileDataRepresentation()
print(imageData)
image = UIImage(data: imageData)
if(self.image == nil)
print("The image is empty")
pdelegate?.previewSegueDelegate(image: self.image!, device: currentCamera!)
【问题讨论】:
【参考方案1】:相机切换逻辑错误。
@IBAction func FlipThe_camera(_ sender: UIButton)
print("Flip Touched")
captureSession.beginConfiguration()
if let inputs = captureSession.inputs as? [AVCaptureDeviceInput]
for input in inputs
captureSession.removeInput(input)
usingFrontCamera = !usingFrontCamera
setupCaptureSession()
setupDevice(usingFrontCamera: usingFrontCamera)
setupInput()
captureSession.commitConfiguration()
startRunningCaptureSession()
您不应在 setupInput()
中再次添加输出。
并且不应在startRunningCaptureSession()
中再次开始运行会话
【讨论】:
以上是关于为啥在 AVCapturePhotoOutput 上调用 .capturePhoto(with:,delegate:) 会导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章
无法仅获取在 Swift 中显示相机(AVCapturePhotoOutput)的 UIView 的屏幕截图
AVCapturePhotoOutput - Xcode 9 Beta 5 中的更改