我开始使用 Xcode 和 swift 用我的 iPhone 拍摄简单的照片。我将几个示例项目归结为下面一个简单的类,该类派生自 AVCapturePhotoCaptureDelegate,具有 Initialize、TakePhoto 方法和回调 photoOutput——即非常简单。为了测试,我创建了一个带有“初始化”和“拍照”按钮的简单应用程序。
当我拍照并调用“photoOutput.capturePhoto”时,它会停止并出现异常“没有活动且已启用的视频连接。”
显然我在归结中错过了一些基本的东西。我从示例项目中遗漏的一件事是预览层...这是否需要活动预览才能运行?这就是缺少“视频”连接的意思吗?为什么会这样要求?
或者我还遗漏了什么?
非常感谢。
import UIKit
import AVFoundation
class cPhotoCaptureNormal: NSObject, AVCapturePhotoCaptureDelegate
{
private let photoOutput = AVCapturePhotoOutput()
public func Initialize()
{
let captureSession = AVCaptureSession()
if let captureDevice = AVCaptureDevice.default(for: AVMediaType.video) {
do {
let input = try AVCaptureDeviceInput(device: captureDevice)
if captureSession.canAddInput(input) {
captureSession.addInput(input)
}
} catch let error {
print("Failed to set input device with error: \(error)")
}
if captureSession.canAddOutput(photoOutput) {
captureSession.addOutput(photoOutput)
}
else
{
print("Failed to add output device")
}
captureSession.startRunning()
}
}
public func TakePhoto()
{
let photoSettings = AVCapturePhotoSettings()
if let photoPreviewType = photoSettings.availablePreviewPhotoPixelFormatTypes.first {
photoSettings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: photoPreviewType]
// EXCEPTION OCCURS ON FOLLOwING LINE
photoOutput.capturePhoto(with: photoSettings, delegate: self)
}
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
guard let imageData = photo.fileDataRepresentation() else { return }
let previewImage = UIImage(data: imageData)
// ... post process and save UIImage
}
}
假设您在调用
Initialize()
之前调用 TakePhoto()
函数,最有可能导致问题的原因是您的 AVCaptureSession
在 Initialize
结束时超出范围。将 captureSession
设为属性而不是局部变量。这将使会话保持活跃并允许您拍照。
您还应该在某个时候致电
captureSession.stopRunning()
。
class cPhotoCaptureNormal: NSObject, AVCapturePhotoCaptureDelegate {
private let photoOutput = AVCapturePhotoOutput()
private let captureSession = AVCaptureSession()
public func initialize() {
if let captureDevice = AVCaptureDevice.default(for: AVMediaType.video) {
do {
let input = try AVCaptureDeviceInput(device: captureDevice)
if captureSession.canAddInput(input) {
captureSession.addInput(input)
}
} catch let error {
print("Failed to set input device with error: \(error)")
}
if captureSession.canAddOutput(photoOutput) {
captureSession.addOutput(photoOutput)
} else {
print("Failed to add output device")
}
captureSession.startRunning()
}
}
public func takePhoto() {
let photoSettings = AVCapturePhotoSettings()
if let photoPreviewType = photoSettings.availablePreviewPhotoPixelFormatTypes.first {
photoSettings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: photoPreviewType]
photoOutput.capturePhoto(with: photoSettings, delegate: self)
}
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
guard let imageData = photo.fileDataRepresentation() else { return }
let previewImage = UIImage(data: imageData)
// ... post process and save UIImage
}
}
在一个不相关的注释中,Swift 中的标准做法是以小写字母开头的函数名称。只有类、结构和枚举名称以大写字母开头。