ios播放系统声音

时间:2014-08-07 06:55:45

标签: ios objective-c audio

我在构建框架AVFoundation中创建了一个带有apple的条形码扫描器。一切都运转良好。

我想添加条形码扫描完成时播放的声音。我的情况就是当我的屏幕上的标签上写着扫描的数字时。

我知道如何播放声音。但声音会一直重复,这是预期的,因为方法(见代码*)总是被调用。

captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection

我所做的是

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    CGRect highlightViewRect = CGRectZero;
    AVMetadataMachineReadableCodeObject *barCodeObject;
    NSString *detectionString = nil;
    NSArray *barCodeTypes = @[AVMetadataObjectTypeUPCECode,AVMetadataObjectTypeCode39Code,AVMetadataObjectTypeCode39Mod43Code,AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypeCode93Code,AVMetadataObjectTypeCode128Code,AVMetadataObjectTypePDF417Code,AVMetadataObjectTypeQRCode,AVMetadataObjectTypeAztecCode];

    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)
        {
            lblresult.text = detectionString;
            break;
        }else
            lblresult.text = @"(none)";
    }
    if(detectionString !=nil && ![lblresult.text isEqual:@""]){
        [self playSound];
    }
    highlightView.frame = highlightViewRect;
}

播放声音的方法

-(void)playSound{
    if(![lblresult.text isEqual:@""]){
    AudioServicesPlaySystemSound(systemSoundID);
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            AudioServicesDisposeSystemSoundID(systemSoundID);
        });
    }
}

我真的不知道应该在哪里调用此方法,因此当标签不为空时,声音只播放一次。

感谢您的帮助和快速解答!

1 个答案:

答案 0 :(得分:0)

听起来每次AVFoundation识别条形码时都会播放声音,只要您的相机指向该条形码,就会多次播放。

我假设你有一个AVCaptureSession,你开始在某个时刻运行(这是导致captureOutput:运行的原因),以及一个预览层来查看相机在屏幕上看到的内容,如下所示:

@property (strong, nonatomic) AVCaptureSession *session;
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *prevLayer;

...

- (void)viewDidLoad
{
    [_session startRunning];

...

如果你在成功扫描后立即调用了stopRunning:就像这样:

if(detectionString !=nil && ![lblresult.text isEqual:@""]){
    [self playSound];
    [_session stopRunning];
}
然后它应该只播放一次声音。但是,您还将在其捕获的最后一帧上冻结预览图层,因此您可能需要考虑调用:

[self.prevLayer removeFromSuperlayer];

这将完全从视图中删除冻结的图像,然后可以添加预览图层并通过以下方式重新启用扫描:

[self.barcodeScanAreaView.layer addSublayer:_prevLayer];
[_session startRunning];

或者,您可以包含一些逻辑,以便在刚刚发生扫描后禁用条形码识别。创建BOOL属性并在成功扫描后更改其值,例如:

if(detectionString !=nil && !wasJustScanned && ![lblresult.text isEqual:@""]){
    [self playSound];
    wasJustScanned = YES;
}

最重要的问题是,何时重新启用扫描。也许您希望用户确认他们想要保留他们刚刚扫描的内容(因此可能是视图下的按钮),或者预览/扫描视图可能是在成功扫描后立即弹出的模态视图。我建议查看现有的应用程序,看看他们做了什么。然而,从根本上说,不重复蜂鸣声的关键是在第一次成功识别条形码后禁用捕获或禁用处理捕获的条形码。