AVCam 项目崩溃于 iPad
AVCam Project Crashes On iPad
Apple 的 AVCam 演示应用程序演示源代码可在此处找到:https://developer.apple.com/library/content/samplecode/AVCam/Introduction/Intro.html 在尝试拍照时崩溃(无论您构建的是 Objective-C 还是 Swift 版本) AVCamCameraViewController/CameraViewController
(Swift) 中捕获照片的行:
[self.photoOutput capturePhotoWithSettings:photoSettings delegate:photoCaptureDelegate];
或(Swift)
self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate)
崩溃时的错误信息是:
2016-11-21 17:44:31.590070 AVCam[2178:2303627] * Terminating app due
to uncaught exception 'NSInvalidArgumentException', reason: '*
-[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] flashMode must be set to a value present in the supportedFlashModes array'
当我检查闪光灯模式数组时,我得到了这个:
(lldb) po [self.photoOutput supportedFlashModes]
<__NSSingleObjectArrayI 0x170007c50>( 0 )
因此,为了添加闪光灯模式,文档说您必须在 AVCapturePhotoSettings
对象中指定要支持的模式。我用这行代码做到了:
photoSettings.flashMode = AVCaptureFlashModeAuto;
或(Swift)
photoSettings.flashMode = .auto
所以我的直觉是这是一个与 12.9" iPad Pro 和 特别相关的错误,我可能需要提交一份雷达,但我想我会问以防有人以前看过它。有什么想法吗?
更新
我也能够复制其他 iPad,所以它似乎不仅仅是 12.9" iPad Pro。
将这一行写入信息 plist
Privacy - Camera Usage Description
添加这个...
let position = self.videoDeviceInput.device.position
photoSettings.flashMode = position == .front || position == .unspecified ? .off : .auto
就在这之前...
self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate)
这应该可以解决问题。
所以根据 Soja 的回答,我决定询问 photoOutput
变量提供的 supportedFlashModes
数组,它是一个 AVCapturePhotoOutput
.
self.inProgressPhotoCaptureDelegates[photoCaptureDelegate.requestedPhotoSettings.uniqueID] = photoCaptureDelegate
if let _ = self.photoOutput.supportedFlashModes.filter({ (mode) -> Bool in
return mode.intValue == AVCaptureFlashMode.auto.rawValue
}).last {
let position = self.videoDeviceInput.device.position
photoSettings.flashMode = position == .front || position == .unspecified ? .off : .auto
} else {
photoSettings.flashMode = .off
}
self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate)
可能有一些更全面的方法可以做到这一点,但这可以确保在尝试使用 .auto
模式之前支持它。这里的差异和问题似乎与设备类型有关,iPhone vs iPad,因为 iPad 的背面没有闪光灯 iPhone 做。换句话说,它在我的 phone.
上运行良好
// 对于在 MacOS 上尝试使用 Apple 提供的 AVCam 示例代码时可能遇到此问题的人,使用 Objective C 提供的代码版本,只需添加这(在 Objective C 中):
AVCaptureDevicePosition position = self.videoDeviceInput.device.position;
if (position == AVCaptureDevicePositionFront)
{
photoSettings.flashMode = AVCaptureFlashModeOff;
}
else
{
photoSettings.flashMode = AVCaptureFlashModeAuto;
}
//right before:
[self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate]
您必须检查设备是否支持"Flash"模式
与:
[self.photoOutput.supportedFlashModes containsObject:[NSNumber numberWithInt:AVCaptureFlashModeOn]])
然后使用:
@property (nonatomic) AVCapturePhotoOutput *photoOutput;
AVCapturePhotoSettings *photoSettings = [AVCapturePhotoSettings photoSettings];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch] && [device hasFlash]){
[device lockForConfiguration:nil];
if([self.photoOutput.supportedFlashModes containsObject:[NSNumber numberWithInt:AVCaptureFlashModeOn]]){
[device setFlashMode:AVCaptureFlashModeOn];
photoSettings.flashMode = AVCaptureFlashModeAuto;
}
else{
photoSettings.flashMode = AVCaptureFlashModeOff;
}
[device unlockForConfiguration];
}
else{
photoSettings.flashMode = AVCaptureFlashModeOff;
[device unlockForConfiguration];
}
然后
[self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate]
@RazvanR 解决方案适用于该 Apple AVCamera 代码,但就在它之前的代码
// NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
不会,需要使用 AVCapturePhotoOutput
Swift版本是
Swift: photoData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer)
...但不知道 Objective-C 版本是什么。
要检查相机是否有闪光灯,请使用该相机上的 AVCaptureDevice.hasFlash
属性。
使用 back/front 位置来猜测这个真的没有意义,因为已经有一些东西可以告诉你它是否有闪光。
在swift中必须检查照片输出是否支持闪光灯模式。
let settings = AVCapturePhotoSettings()
if photoOutput.supportedFlashModes.contains(.on) {
settings.flashMode = self.flashMode
} else {
settings.flashMode = .off
}
self.photoOutput?.capturePhoto(with: settings, delegate: self)
不需要检查相机位置,我们只需要检查相机是否有闪光灯,并根据它设置闪光灯模式。
photoSettings.flashMode = AVCaptureDevice.default(for: AVMediaType.video)!.hasFlash ? .on : .off
Apple 的 AVCam 演示应用程序演示源代码可在此处找到:https://developer.apple.com/library/content/samplecode/AVCam/Introduction/Intro.html 在尝试拍照时崩溃(无论您构建的是 Objective-C 还是 Swift 版本) AVCamCameraViewController/CameraViewController
(Swift) 中捕获照片的行:
[self.photoOutput capturePhotoWithSettings:photoSettings delegate:photoCaptureDelegate];
或(Swift)
self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate)
崩溃时的错误信息是:
2016-11-21 17:44:31.590070 AVCam[2178:2303627] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] flashMode must be set to a value present in the supportedFlashModes array'
当我检查闪光灯模式数组时,我得到了这个:
(lldb) po [self.photoOutput supportedFlashModes] <__NSSingleObjectArrayI 0x170007c50>( 0 )
因此,为了添加闪光灯模式,文档说您必须在 AVCapturePhotoSettings
对象中指定要支持的模式。我用这行代码做到了:
photoSettings.flashMode = AVCaptureFlashModeAuto;
或(Swift)
photoSettings.flashMode = .auto
所以我的直觉是这是一个与 12.9" iPad Pro 和 特别相关的错误,我可能需要提交一份雷达,但我想我会问以防有人以前看过它。有什么想法吗?
更新
我也能够复制其他 iPad,所以它似乎不仅仅是 12.9" iPad Pro。
将这一行写入信息 plist
Privacy - Camera Usage Description
添加这个...
let position = self.videoDeviceInput.device.position
photoSettings.flashMode = position == .front || position == .unspecified ? .off : .auto
就在这之前...
self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate)
这应该可以解决问题。
所以根据 Soja 的回答,我决定询问 photoOutput
变量提供的 supportedFlashModes
数组,它是一个 AVCapturePhotoOutput
.
self.inProgressPhotoCaptureDelegates[photoCaptureDelegate.requestedPhotoSettings.uniqueID] = photoCaptureDelegate
if let _ = self.photoOutput.supportedFlashModes.filter({ (mode) -> Bool in
return mode.intValue == AVCaptureFlashMode.auto.rawValue
}).last {
let position = self.videoDeviceInput.device.position
photoSettings.flashMode = position == .front || position == .unspecified ? .off : .auto
} else {
photoSettings.flashMode = .off
}
self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate)
可能有一些更全面的方法可以做到这一点,但这可以确保在尝试使用 .auto
模式之前支持它。这里的差异和问题似乎与设备类型有关,iPhone vs iPad,因为 iPad 的背面没有闪光灯 iPhone 做。换句话说,它在我的 phone.
// 对于在 MacOS 上尝试使用 Apple 提供的 AVCam 示例代码时可能遇到此问题的人,使用 Objective C 提供的代码版本,只需添加这(在 Objective C 中):
AVCaptureDevicePosition position = self.videoDeviceInput.device.position;
if (position == AVCaptureDevicePositionFront)
{
photoSettings.flashMode = AVCaptureFlashModeOff;
}
else
{
photoSettings.flashMode = AVCaptureFlashModeAuto;
}
//right before:
[self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate]
您必须检查设备是否支持"Flash"模式 与:
[self.photoOutput.supportedFlashModes containsObject:[NSNumber numberWithInt:AVCaptureFlashModeOn]])
然后使用:
@property (nonatomic) AVCapturePhotoOutput *photoOutput;
AVCapturePhotoSettings *photoSettings = [AVCapturePhotoSettings photoSettings];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch] && [device hasFlash]){
[device lockForConfiguration:nil];
if([self.photoOutput.supportedFlashModes containsObject:[NSNumber numberWithInt:AVCaptureFlashModeOn]]){
[device setFlashMode:AVCaptureFlashModeOn];
photoSettings.flashMode = AVCaptureFlashModeAuto;
}
else{
photoSettings.flashMode = AVCaptureFlashModeOff;
}
[device unlockForConfiguration];
}
else{
photoSettings.flashMode = AVCaptureFlashModeOff;
[device unlockForConfiguration];
}
然后
[self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate]
@RazvanR 解决方案适用于该 Apple AVCamera 代码,但就在它之前的代码
// NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
不会,需要使用 AVCapturePhotoOutput
Swift版本是
Swift: photoData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer)
...但不知道 Objective-C 版本是什么。
要检查相机是否有闪光灯,请使用该相机上的 AVCaptureDevice.hasFlash
属性。
使用 back/front 位置来猜测这个真的没有意义,因为已经有一些东西可以告诉你它是否有闪光。
在swift中必须检查照片输出是否支持闪光灯模式。
let settings = AVCapturePhotoSettings()
if photoOutput.supportedFlashModes.contains(.on) {
settings.flashMode = self.flashMode
} else {
settings.flashMode = .off
}
self.photoOutput?.capturePhoto(with: settings, delegate: self)
不需要检查相机位置,我们只需要检查相机是否有闪光灯,并根据它设置闪光灯模式。
photoSettings.flashMode = AVCaptureDevice.default(for: AVMediaType.video)!.hasFlash ? .on : .off