IOS Правильно остановить AVCaptureSession
У меня возникла проблема при тестировании нового сканирования штрих-кода api в iOS 7. Этот пример (приложение с одним представлением) отлично работает, но я хочу остановить 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.
}
Ответы
Ответ 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;
Ответ 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];
});
}
}
}