iOS正确停止AVCaptureSession

我在iOS 7中testing新的条形码扫描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. } 

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

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

}