iOS Correctly stop AVCaptureSession

i got a problem while testing the new barcode scanning api in iOS 7. This example (single view application) works fine, but i want to stop the AVCaptureSession and show the first view after an EAN code is recognized by the camera.

[self.captureSession startRunning]; does not work.

  • How to rotate a UICollectionView similar to the photos app and keep the current view centered?
  • How to add a button to the MKPointAnnotation?
  • How to call an Objective-C category method in Swift
  • Swift: Problems with custom UIView.transition?
  • Barcode Generation from within iOS App
  • How to send Extra parameters in payload via Amazon SNS Push Notification
  • How do i correctly stop the AVCaptureSession?

    #import "ViewController.h"
    #import <AVFoundation/AVFoundation.h>
    @interface ViewController ()  <AVCaptureMetadataOutputObjectsDelegate>
    @property (strong) AVCaptureSession *captureSession;
    @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];
            [self.captureSession addInput:videoInput];
            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 Solutions Collect From Internet About “iOS Correctly stop AVCaptureSession”

    You can actually stop the AVCaptureSession thus:

    [self.captureSession stopRunning];

    But I suspect what you really want to do is to freeze the screen. It’s helpful to keep a reference to your previewLayer in a property. Then:

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

    You can try something like this to freeze the screen and then unfreeze it after a couple of seconds

    - (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];

    full takedown:

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

    you should call the performViewController in the main thread. such as below:

    -(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];