我一直在努力让我的翻页按钮继续工作并且一直收到错误
[AVCapturePhotoOutput capturePhotoWithSettings:delegate:]没有有效和启用的视频连接'
我能够通过添加一行代码来修复错误,以便在触摸翻页按钮时移除现有的captureSession.outputs
,并将所有AVcaptureDevice
设置移至DispatchQueue.main.async
而不是单独的DispatchQueue
,sessionQueue = DispatchQueue(label: "session queue")
下面是翻转按钮的代码
@IBAction func FlipThe_camera(_ sender: UIButton) {
print("Flip Touched")
self.captureSession.beginConfiguration()
if let inputs = self.captureSession.inputs as? [AVCaptureDeviceInput] {
for input in inputs {
self.captureSession.removeInput(input)
print("input removed")
}
//This seemed to have fixed it
for output in self.captureSession.outputs{
captureSession.removeOutput(output)
print("out put removed")
}
}
self.usingFrontCamera = !self.usingFrontCamera
self.setupCaptureSession()
self.setupDevice(usingFrontCamera: self.usingFrontCamera)
self.setupInput()
self.captureSession.commitConfiguration()
self.startRunningCaptureSession()
}
将setUpCatureSession()
和setupInput()
中涉及的所有代码放到Dispatch.Queue.main
上是否有任何损害?
我已将这两个函数中包含的代码从自己的线程转移到主线程上,这是一种不好的做法吗?谢谢你的建议?
func setupDevice(usingFrontCamera:Bool = false){
DispatchQueue.main.async {
//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() {
DispatchQueue.main.async {
// sessionQueue.async {
do {
let captureDeviceInput = try AVCaptureDeviceInput(device: self.currentCamera!)
if self.captureSession.canAddInput(captureDeviceInput) {
self.captureSession.addInput(captureDeviceInput)
print("input added")
}
self.photoOutPut = AVCapturePhotoOutput()
self.photoOutPut?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format:[AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
if self.captureSession.canAddOutput(self.photoOutPut!) {
self.captureSession.addOutput(self.photoOutPut!)
print("output added")
}
} catch {
print(error)
}
}
}
以下是完整的代码:
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 backCamera: AVCaptureDevice?
var frontCamera: AVCaptureDevice?
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()
}
func setupCaptureSession(){
captureSession.sessionPreset = AVCaptureSession.Preset.photo
sessionQueue = DispatchQueue(label: "session queue")
}
func setupDevice(usingFrontCamera:Bool = false){
DispatchQueue.main.async {
//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() {
DispatchQueue.main.async {
// sessionQueue.async {
do {
let captureDeviceInput = try AVCaptureDeviceInput(device: self.currentCamera!)
if self.captureSession.canAddInput(captureDeviceInput) {
self.captureSession.addInput(captureDeviceInput)
print("input added")
}
self.photoOutPut = AVCapturePhotoOutput()
self.photoOutPut?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format:[AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
if self.captureSession.canAddOutput(self.photoOutPut!) {
self.captureSession.addOutput(self.photoOutPut!)
print("output added")
}
} 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) {
print("Camera button tapped")
let settings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])
if let photoOutputConnection = self.photoOutPut?.connection(with: .video){
photoOutputConnection.videoOrientation = (cameraPreviewLayer?.connection?.videoOrientation)!
}
photoOutPut?.capturePhoto(with: settings, delegate: self as AVCapturePhotoCaptureDelegate)
}
@IBAction func FlipThe_camera(_ sender: UIButton) {
print("Flip Touched")
self.captureSession.beginConfiguration()
if let inputs = self.captureSession.inputs as? [AVCaptureDeviceInput] {
for input in inputs {
self.captureSession.removeInput(input)
print("input removed")
}
//This seemed to have fixed it
for output in self.captureSession.outputs{
captureSession.removeOutput(output)
print("out put removed")
}
}
self.usingFrontCamera = !self.usingFrontCamera
self.setupCaptureSession()
self.setupDevice(usingFrontCamera: self.usingFrontCamera)
self.setupInput()
self.captureSession.commitConfiguration()
self.startRunningCaptureSession()
}
}
extension MainCameraCollectionViewCell: AVCapturePhotoCaptureDelegate{
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
print("Im in the photo out put delgate")
if let imageData = photo.fileDataRepresentation(){
print(imageData)
image = UIImage(data: imageData)
if(self.image == nil){
print("The image is empty")
}
print("The capture session is running photoOutput: \(captureSession.isRunning)")
print("The capture session has been interupted photoOutput: \(captureSession.isInterrupted)")
pdelegate?.previewSegueDelegate(image: self.image!, device: currentCamera!)
}
else{
print("The photoOutput delegate error is \(String(describing: error))")
}
}
}