iOS正确停止AVCaptureSession

13

在测试iOS 7中的新条形码扫描API时,我遇到了一个问题。这个例子(单视图应用程序)运行良好,但是我想要在相机识别出EAN码后停止AVCaptureSession并显示第一个视图。

[self.captureSession startRunning];不起作用。

我该如何正确地停止AVCaptureSession?

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface ViewController ()  <AVCaptureMetadataOutputObjectsDelegate>

@property (strong) AVCaptureSession *captureSession;

@end

@implementation ViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
    self.captureSession = [[AVCaptureSession alloc] init];
    AVCaptureDevice *videoCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error = nil;
    AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoCaptureDevice error:&error];
    if(videoInput)
        [self.captureSession addInput:videoInput];
    else
        NSLog(@"Error: %@", error);

    AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init];
    [self.captureSession addOutput:metadataOutput];
    [metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [metadataOutput setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code]];

    AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
    previewLayer.frame = self.view.layer.bounds;
    [self.view.layer addSublayer:previewLayer];

    [self.captureSession startRunning];

}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    for(AVMetadataObject *metadataObject in metadataObjects)
    {
        AVMetadataMachineReadableCodeObject *readableObject = (AVMetadataMachineReadableCodeObject *)metadataObject;
        if([metadataObject.type isEqualToString:AVMetadataObjectTypeQRCode])
        {
            NSLog(@"QR Code = %@", readableObject.stringValue);
        }
        else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeEAN13Code])
        {
            NSLog(@"EAN 13 = %@", readableObject.stringValue);



        }
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
2个回答

29

你可以通过以下方式停止 AVCaptureSession:

[self.captureSession stopRunning];

但我猜想你真正想做的是冻结屏幕。将previewLayer存储在属性中会很有帮助。然后:

[[self.previewLayer connection] setEnabled:NO];

你可以尝试像这样冻结屏幕,然后在几秒钟后取消冻结

- (void)     captureOutput:(AVCaptureOutput *)captureOutput 
  didOutputMetadataObjects:(NSArray *)metadataObjects 
            fromConnection:(AVCaptureConnection *)connection
{   
    [[self.previewLayer connection] setEnabled:NO];

    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 
                                  (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [[self.previewLayer connection] setEnabled:YES];

    });

    ...

}

更新
完全下架:

[self.captureSession stopRunning];
[self.previewLayer removeFromSuperlayer];
self.previewLayer = nil;
self.captureSession = nil;

嗨,Foundry,谢谢您的回复。我只想在变量中解析已识别的EAN以供以后使用,并立即关闭捕获会话,无需延迟。 - Boeringer

0

你应该在主线程中调用performViewController方法,例如:

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
if (metadataObjects != nil && [metadataObjects count] > 0) {
    AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
    if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {

        [self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO];
        // should call the view controller transfer method in the main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            [self performSegueWithIdentifier:@"show first view controller" sender: self];
        });

    }
}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接