Scanning Barcodes with iOS 7 (Objective-C)

Torrey Betts / Thursday, October 10, 2013

Introduction

With the release of iOS 7, Apple included the ability to detect barcodes through its AV Foundation framework. The supported types are:

  • UPC-A
  • UPC-E
  • Code 39
  • Code 39 mod 43
  • Code 93
  • Code 128
  • EAN-8
  • EAN-13
  • Aztec
  • PDF417
  • QR

Detecting a Barcode

Detecting a barcode is quite simple. To start, we initialize a capture session, device, input and output. The output sets its delegate for processing of the detections and the metadata object types to detect are set. In this example, all the available types are set, and are then later filtered using the captureOutput:didOutputMetadataObjects:fromConnection: AVCaptureMetadataOutputObjectsDelegate delegate method.

    _session = [[AVCaptureSession alloc] init];
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error = nil;

    _input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error];
    if (_input) {
        [_session addInput:_input];
    } else {
        NSLog(@"Error: %@", error);
    }

    _output = [[AVCaptureMetadataOutput alloc] init];
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [_session addOutput:_output];

    _output.metadataObjectTypes = [_output availableMetadataObjectTypes];

    _prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    _prevLayer.frame = self.view.bounds;
    _prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.view.layer addSublayer:_prevLayer];

    [_session startRunning];

Next, using the captureOutput:didOutputMetadataObjects:fromConnection:AVCaptureMetadataOutputObjectsDelegate delegate method we create an array containing the supported barcode types and filter through the detected metadata objects. Once a supported type has been detected we grab the detection rectangle and the barcode's string value. The string value is displayed at the bottom of the screen and the detection rectangle is shown by using a transparent UIView that has a border set.

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    CGRect highlightViewRect = CGRectZero;
    AVMetadataMachineReadableCodeObject *barCodeObject;
    NSString *detectionString = nil;
    NSArray *barCodeTypes = @[AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode39Mod43Code,
            AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeCode128Code,
            AVMetadataObjectTypePDF417Code, AVMetadataObjectTypeQRCode, AVMetadataObjectTypeAztecCode];

    for (AVMetadataObject *metadata in metadataObjects) {
        for (NSString *type in barCodeTypes) {
            if ([metadata.type isEqualToString:type])
            {
                barCodeObject = (AVMetadataMachineReadableCodeObject *)[_prevLayer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
                highlightViewRect = barCodeObject.bounds;
                detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
                break;
            }
        }

        if (detectionString != nil)
        {
            _label.text = detectionString;
            break;
        }
        else
            _label.text = @"(none)";
    }

    _highlightView.frame = highlightViewRect;
}

See it in Action

The following animated image demonstrates this sample project and the detection of a UPC-A barcode.

Download the Example Project

The Xcode project source code for this post can be downloaded by clicking this link.

Update (April 23rd 2014) - Support for rendering barcodes was added to NucliOS 2014 Volume 1, the following blog post details the supported barcode types. (Blog Post Link)

By Torrey Betts