【问题标题】:iOS Correctly stop AVCaptureSessioniOS 正确停止 AVCaptureSession
【发布时间】:2014-01-11 20:11:54
【问题描述】:

我在 iOS 7 中测试新的条码扫描 API 时遇到问题。此示例(单视图应用程序)工作正常,但我想停止 AVCaptureSession 并在相机识别 EAN 代码后显示第一个视图。

[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.
}

【问题讨论】:

    标签: ios iphone objective-c ios7


    【解决方案1】:

    您实际上可以这样停止 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;
    

    【讨论】:

    • 您好铸造厂,感谢您的回复。我只想解析变量中识别的 ean 以供以后使用,并立即关闭捕获会话,没有延迟。
    【解决方案2】:

    你应该在主线程中调用 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];
            });
    
        }
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多