使AVCaptureSession只扫描一次

时间:2014-01-26 09:21:33

标签: ios7 avcapturesession

如何才能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);
    }
    }

任何帮助表示感谢。

1 个答案:

答案 0 :(得分:2)

iOS中的条形码扫描器是作为AV管道的一部分实现的。扫描仪将查看每个捕获的图像,并在识别出图像中的条形码时调用代理。因此,如果它识别出30个连续图像中的条形码,它将连续30次呼叫代表。

由您的应用程序决定如何处理此类案例。某些应用可能希望不断了解已识别的条形码。您显然只对单个识别事件感兴趣。要实现这一目标,您有以下几种选择:

  1. 完全停止视频捕获。如果您的应用程序在捕获条形码时切换到不同的场景,这通常是合适的。

  2. 从AV管道中删除条形码扫描器(AVCaptureMetadataOutput)。

  3. 记住最后捕获的条形码和上次捕获的时间,如果在最后一次捕获后的2到3秒内再次捕获相同的条形码,则不要动作。

  4. 您发布的代码不完整。可能你已经实现了类似于选项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];