【发布时间】:2020-08-30 00:17:06
【问题描述】:
我是 Swift 的初学者,使用 Swift 5 和 XCode 11.5 这是我创建相机的代码。我希望它已经足够了!
override func viewDidAppear(_ animated: Bool) {
setupCaptureSession()
setupDevice()
setupInputOutput()
setupPreviewLayer()
captureSession.startRunning()
}
func setupCaptureSession() {
captureSession.sessionPreset = AVCaptureSession.Preset.photo
}
func setupDevice() {
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified)
let devices = deviceDiscoverySession.devices
for device in devices {
if device.position == AVCaptureDevice.Position.back {
backCamera = device
} else if device.position == AVCaptureDevice.Position.front {
frontCamera = device
}
}
currentDevice = backCamera
}
func setupInputOutput() {
do {
let captureDeviceInput = try AVCaptureDeviceInput(device: currentDevice!)
if let inputs = captureSession.inputs as? [AVCaptureDeviceInput] {
for input in inputs {
captureSession.removeInput(input)
}
}
captureSession.addInput(captureDeviceInput)
photoOutput = AVCapturePhotoOutput()
photoOutput!.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey : AVVideoCodecType.jpeg])], completionHandler: nil)
captureSession.addOutput(photoOutput!)
} catch {
print(error)
}
}
func setupPreviewLayer() {
self.cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
self.cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
self.cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
self.cameraPreviewLayer?.frame = view.frame
self.view.layer.insertSublayer(self.cameraPreviewLayer!, at: 0)
}
@IBAction func rotateCamera(_ sender: Any) {
captureSession.beginConfiguration()
// Change the device based on the current camera
let newDevice = (currentDevice?.position == AVCaptureDevice.Position.back) ? frontCamera : backCamera
// Remove all inputs from the session
for input in captureSession.inputs {
captureSession.removeInput(input as! AVCaptureDeviceInput)
}
// Change to the new input
let cameraInput:AVCaptureDeviceInput
do {
cameraInput = try AVCaptureDeviceInput(device: newDevice!)
} catch {
print(error)
return
}
if captureSession.canAddInput(cameraInput) {
captureSession.addInput(cameraInput)
}
currentDevice = newDevice
captureSession.commitConfiguration()
}
我正在尝试使用 AVFoundation 创建相机,但我收到一条错误消息:
线程 1:异常:“*** -[AVCaptureSession addOutput:] 无法添加输出
所以我上网查了一下,发现这篇帖子:AVCapture Session To Capture Image SWIFT 提到了类似的错误,但因为它使用的是旧版本,所以我尝试重新创建它。然而,我能得到的最远的是:
DispatchQueue.global(qos: .userInteractive).async { // 1
self.captureSession.addOutput(self.photoOutput!)
try self.captureSession.addInput( AVCaptureDeviceInput(device: self.currentDevice!))
//supposed to add error here but couldn't do it
self.captureSession.sessionPreset = AVCaptureSession.Preset.photo
var previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
previewLayer.frame = self.cameraView.layer.bounds
//In my project it said there was no member cameraView of UIViewController.
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
DispatchQueue.main.async { // 2
// 3
self.cameraView.layer.addSublayer(previewLayer)
self.captureSession.startRunning()
}
}
由于从那时起许多方法已被弃用,我很难找到新的方法,而且我什至无法将错误添加为参数,因为它是调用中的额外参数。如果有人能帮我弄清楚如何解决这个多输入问题,我将不胜感激。我尽了最大的努力,但老实说我找不到任何解决方案。
谢谢!
编辑:我添加了更多代码。
编辑 2:对于任何关注的人来说,问题是我在视图中调用它们时确实出现了多次输出,这要归功于马特(在 cmets 中)的帮助。我通过使用 view did load 修复了它
【问题讨论】:
-
您没有显示足够的代码。从抱怨“多个输出”的错误消息中,听起来您不止一次配置捕获会话。但是如果不知道更多关于捕获会话的信息,你对它说了什么,以及
inputOutput是如何被调用的,就很难说什么了。 -
嗨,马特,感谢您的回复。我添加了这段代码的其余部分。我希望这就够了。
-
viewDidAppear可以多次调用。因此,在这种情况下,您每次都在运行该代码... -
那我该如何解决呢?我是否应该将方法从视图中移到确实加载的视图中?谢谢!
-
你可以。或者只是看一下会话,如果你已经初始化了就不要初始化它。
标签: ios swift avfoundation xcode11.5