Tutorial

Building a Simple Barcode Reader App in Swift


In the hand of the clerk at the local grocer’s checkout line, helping to check in bags and passengers at the airport, or assisting in the tedious inventory process at a major retailer, a barcode scanner is simply a handy tool. In fact, they have even made their way to the consumer for smart shopping, cataloging, and other purposes. So, let’s make one for the iPhone!

Fortunately for us, Apple has made the barcode scanning process a breeze to implement. We will be diving into the world of AV Foundation Framework to build a neat little iPhone app that reads barcodes on CDs, gets some important information about the Album, and prints it to the app’s view. Reading the barcodes is cool and important, but we’ll take it a step further and do something neat with the barcode number that we receive.

It should probably go without saying, but a barcode scanning app will only work on a device equipped with a camera. With that in mind, let’s grab our camera-equipped iOS devices and get started!

About CDBarcodes

The name of the app we’re building today is CDBarcodes – pretty clever. When our device detects a barcode, we will clean up the code and send it to the Discogs database to get the album’s name and artist in addition to the year of its release. Discogs has a monstrously large database of recorded music, so it’s pretty likely we will get the information that we seek.

Download the starter project for CDBarcodes.

Simple Barcode App

Along with their impressive database, Discogs has a useful API that we will query. We will only be touching a little piece of what Discogs offers for developers, however, but it’ll be plenty to get a fun little app running.

Discogs

Let’s navigate to Discogs and get rolling. First, we’ll need to log in or register for a Discogs account. After logging in, scroll to the bottom of the screen. In the footer, in the left-most column, click API.

api_button_bottom

In the Discogs API, again, in the column on the left side, in the Database section, click Search.

api_database_search

This is the endpoint from which we will query. We’ll be getting album information from both the “title” and “year” parameters.

Now would be a good time to record the URL for our query into CDBarcodes. In Constants.swift, add https://api.discogs.com/database/search?q= to DISCOGS_AUTH_URL as a constant value.

Now, well be able to access the URL using our handy DISCOGS_AUTH_URL throughout the app.

Back in the Discogs API, lets make a new app and get some credentials. In the navigation bar, at the top of the page, tap Create an App. Then, tap the Create an Application button.

discogs_create_app_button

For the Application Name, enter “CDBarcodes Your Name”, or some suitable variation. For the description, the following will suffice:

“This is an iOS app that reads barcodes from CDs and displays information about the albums.”

Then, click the Create Application button.

On the resulting screen, we will find the credentials that will allow us to make use of our barcode number.

Copy the Consumer Key, and paste it into DISCOGS_KEY in Constants.swift.

Then, copy the Consumer Secret, and paste it into DISCOGS_SECRET in Constants.swift.

As with the URL, we’ll have convenient access to these values throughout CDBarcodes.

discogs_create_name_description

CocoaPods

To communicate with the Discogs API, we’ll be using the fantastic dependency manager, CocoaPods. For more information on CocoaPods, and for instructions on installing it, have a peek at CocoaPods’ site.

Through CocoaPods, we’ll be leveraging Alamofire for networking and SwiftyJSON to handle the JSON returned from Discogs.

Let’s introduce them to CDBarcodes!

With CocoaPods installed, and an open Terminal, navigate to CDBarcodes and initialize CocoaPods in the Xcode project with the following:

Open the Podfile in Xcode:

Type or paste the following into the Podfile so it appears as below:

Finally, run the following command to download Alamofire and SwiftyJSON:

It’s time to get back to Xcode! Be sure to open CDBarcodes.xcworkspace whenever working on the app.

The Barcode Reader

The AV Foundation Framework provides the tools that we will use to build our barcode reader. Here’s a little rundown of what’s involved in the process.

  • AVCaptureSession will manage data form the camera – input to output.
  • The AVCaptureDevice is the physical device and its properties. AVCaptureSession receives input data from the AVCaptureDevice.
  • AVCaptureDeviceInput captures data from the input device.
  • AVCaptureMetadataOutput forwards metadata objects to be processed by a delegate object.

In BarcodeReaderViewController.swift, our first step is to import AVFoundation.

We’ll need to conform to AVCaptureMetadataOutputObjectsDelegate.

In viewDidLoad(), we’ll get our barcode reading engine running.

First, create an AVCaptureSession object and set the AVCaptureDevice. Then, we’ll create an input object and add it to the AVCaptureSession.

If, by chance, the device doesn’t have a camera, scanning isn’t possible. As such, we’ll need a failure method. Here, we’ll alert the user to look around for an iOS device with a camera so we can scan and research some CD barcodes.

Back in viewDidLoad(), after adding the input to the session, we create the AVCaptureMetadataOutput and add it to the session. We will send the captured data to the delegate object via a serial queue.

The next step is to state the type of barcodes for which we should scan. For our purposes, we will be looking for EAN-13 barcodes. Interestingly, not all barcodes that we will scan will be EAN-13 barcodes; some will be UPC-A. This can cause a problem.

Apple converts UPC-A barcodes to EAN-13 by adding a 0 at the front. UPC-A barcodes are only 12 digits; whereas, EAN-13 barcodes are, as one would imagine, 13 digits. The great thing about this automatic conversion is that we can look for metadataObjectTypes AVMetadataObjectTypeEAN13Code, and both EAN-13 and UPC-A barcodes will be read. The tricky part is that this conversion technically changes the barcode and will thoroughly confuse Discogs. We’ll be handling this situation shortly, however.

Yet again, if there is an issue with the camera, we’ll need to send the user to scanningNotPossible().

Now that we have this wonderful functionality, we need to see it! We’ll use AVCaptureVideoPreviewLayer to display the video in the full size of the screen.

Finally, we can start the capture session.

In captureOutput:didOutputMetadataObjects:fromConnection, we celebrate, as our barcode reader found something!

First, we will get the first object from the metadataObjects array and convert it into machine readable code. Then, we will send that readableCode, as a string, to barcodeDetected().

Before we move on to barcodeDetected(), however, we will provide some user feedback in the form of vibration and stop the capture session. If, by chance we forget to stop the session, get ready for a lot of vibrating. That’s a good reason for a case!

We have some work to perform in barcodeDetected(). Our first task is to follow up our vibration with an alert to state that we’ve found a barcode. Then, we turn our find into something we can really use.

The spaces must be removed from the code. After it is free of white space, we need to determine if the barcode is of the EAN-13 or UPC-A format. If it is EAN-13, we’re already in good shape. If it is a UPC-A barcode, it has been converted to EAN-13, and we need to return it to its original format.

As we’ve discussed, Apple adds a 0 to the front of UPC-A barcodes to convert them to EAN-13, so we should start by determining if there is a 0 at the beginning of the code. If so, we need to remove it. Without this step, Discogs won’t recognize the number, and we won’t get our data.

After we get our cleaned-up barcode strings, we ship them off to DataService.searchAPI() and pop BarcodeReaderViewController.swift.

Before moving on from BarcodeReaderViewController.swift, below viewDidLoad(), we will add viewWillAppear() and viewWillDisappear(). viewWillAppear() will start the capture session; whereas, viewWillDisappear() will stop the session.

The Data Service

In DataService.swift, we’ll first import Alamofire and SwiftyJSON.

Next, we will declare some variables to store our raw data, as returned from Discogs. As thoughtfully suggested by Bionik6, we’ll use the handy private(set) approach to avoid clogging up the works with getters.

Then, we build our Alamofire GET request. Here, the JSON is parsed, and we get our album’s title and year. We’ll assign the raw title and year strings to ALBUM_FROM_DISCOGS and YEAR_FROM_DISCOGS, which we will use shortly to initialize our Album.

Now that we have data from Discogs, we want to let the world know; well, we really only want to let AlbumDetailsViewController.swift know. That calls for a notification.

The Album Model

In our Album model, Album.swift, we’ll craft the Album to suit our needs. The model will take the raw artistAlbum and albumYear strings and add a touch of user friendly to them. We’ll be able to access the perfected album and year variables for display in our AlbumDetailsViewController.swift.

Time to Show Album Data!

In viewDidLoad(), let’s set the labels to point us toward the barcode reader. Then, we need to add the observer for the NSNotification, so our posted notification can be herd. We’ll also remove the observer in deinit.

When the notification is observed, setLabels() will be called. Here, we’ll initialize the Album with the raw strings from DataService.swift. The labels will display the perfected strings from the Album.

Testing CDBarcodes

We have an app! Sure, we could have just flipped the CD over a couple of times to determine the album name, artist, and year of release, but this is way more fun! To best test CDBarcodes, we should find several CDs or records (vinyl). This way, it is more likely that we will encounter examples that have EAN-13 and UPC-A barcodes. We can handle both of them!

When navigating to BarcodeReaderViewController in CDBarcodes, look out for glares and be sure to let the camera focus on the barcode.

Here is the completed version of CDBarcodes.

In Conclusion

The barcode reader is a very useful tool for business people, savvy shoppers, and regular people. For this reason, it’s good for developers to have some experience working with them.

As we’ve seen, though, the fun only starts with the scanner. After the data is received, there can be funny little issues for which we much account in order to use the data, for example, EAN-13 versus UPC-A. We found a way to manipulate the data to suit our needs, and we were good to go.

A great next step would be to explore some other metadataObjectTypes and some new APIs. The possibilities are limitless and the experience is priceless.

Tutorial
Building a Full Screen Camera App Using AVFoundation
Tutorial
Advanced Parse Tips: PFObject Subclassing, Caching, Access Control and User Signup
Tutorial
Design Patterns in Swift #2: Observer and Memento
Shares