Scanning Barcodes with iOS 7 (Objective-C)

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


Comments  (7 )

Bald && Bearded
on Mon, Oct 14 2013 11:14 AM

Introduction So Torrey B. here at Infragistics wrote a sample app showing off the bar code scanning capabilities

diego caridei
on Tue, Nov 12 2013 5:08 PM

It's possible read the code from an uiimage?

Jorge Flor
on Tue, Nov 19 2013 8:00 AM

Hi Torrey,

Did you know some way to read an bar code by line ?

Read bar to bar...

David Phlix
on Wed, Jan 15 2014 4:17 AM

Hi,

I did try your sample code and it works like a charm except for one thing :

It looks like the "break" inside the loop (if (detectionString != nil)

       {

           _label.text = detectionString;

           break;

       }) is never called. If you put a NSLog after the break, you can see that it keeps on writing your comment over and over again till you get your camera out of the QR Code.

I would like to perform a segue just after the break, the problem is that it's performing the segue over and over till the app crash...

Am I missing something ?

Thanks for the help.

Torrey Betts
on Wed, Jan 15 2014 7:54 AM

David,

The detection in this sample is using an AV capture, which means it will continuously run and attempt detections. You would need to call the stopRunning method on _session and then trigger your seque.

Torrey Betts
on Wed, Jan 15 2014 8:01 AM

Jorge,

That is not possible, a scanner needs to read an entire barcode to detect it.

Diego,

From what I see in Apple's API, they don't have CIDetector constants for barcodes, you would need to use the AV method shown in this post.

David Phlix
on Thu, Jan 16 2014 9:34 AM

Torrey,

The solution is so simple that I feel a little dumb !

Thanks a lot...

Add a Comment

Please Login or Register to add a comment.