如何才能AVCaptureSession
仅扫描AVCaptureMetadataOutput
ONCE。我一直有扫描一个条码超过30次的问题,将扫描声延迟大约2-3秒然后它发出哔哔声(字面意思)并显示~30 UIAlertView
s !!
下面的代码是我尝试只扫描一次......
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
CGRect highlightViewRect = CGRectZero;
AVMetadataMachineReadableCodeObject *barCodeObject;
NSString *detectionString = nil;
NSArray *barCodeTypes = @[AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode39Mod43Code];
for (AVMetadataObject *metadata in metadataObjects) {
for (NSString *type in barCodeTypes) {
if ([metadata.type isEqualToString:type])
{
barCodeObject = (AVMetadataMachineReadableCodeObject *)[_prevLayer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
highlightViewRect = barCodeObject.bounds;
detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
break;
}
}
if (detectionString != nil)
{
[_session removeOutput:_output];
[_session stopRunning];
_session = nil;
_output = nil;
[_prevLayer removeFromSuperlayer];
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/barcodeBeep.wav", [[NSBundle mainBundle] resourcePath]]];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audioPlayer play];
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
}
任何帮助表示感谢。
答案 0 :(得分:2)
iOS中的条形码扫描器是作为AV管道的一部分实现的。扫描仪将查看每个捕获的图像,并在识别出图像中的条形码时调用代理。因此,如果它识别出30个连续图像中的条形码,它将连续30次呼叫代表。
由您的应用程序决定如何处理此类案例。某些应用可能希望不断了解已识别的条形码。您显然只对单个识别事件感兴趣。要实现这一目标,您有以下几种选择:
完全停止视频捕获。如果您的应用程序在捕获条形码时切换到不同的场景,这通常是合适的。
从AV管道中删除条形码扫描器(AVCaptureMetadataOutput)。
记住最后捕获的条形码和上次捕获的时间,如果在最后一次捕获后的2到3秒内再次捕获相同的条形码,则不要动作。
您发布的代码不完整。可能你已经实现了类似于选项2(和/或1)的东西。这些选项可能不够,因为AV管道可能有几个帧的积压。一旦停止捕获,它将继续处理已捕获但未处理条形码的帧。
我预计大约有五个帧在进行中。如果您真的遇到最多30帧,则表明您的主线程太忙而无法跟上捕获过程。
所以最好的方法是实现选项3(除了你已有的选项)并确保你的主线程不太忙。
if (detectionString != nil)
{
if ([detectionString isEqualToString:_lastCapturedBarcode]
&& [_lastCaptureTime timeIntervalSinceNow] < -3.0)
return; // do nothing; the barcode was already captured
_lastCapturedBarcode = detectionString;
_lastCapturedBarcode = [NSDate date];
[_session removeOutput:_output];
[_session stopRunning];
_session = nil;
_output = nil;
[_prevLayer removeFromSuperlayer];