Xcode 6.2: Swift iOS App That Reads Bar Codes

In my last post, I spoke about reading barcodes in iOS. I’m sure others have also spoken on the topic. Certainly there are some apps out there. For example there is a nice QR code reader called QR Code Reader from Kaywa. It’s a nice little free utility for iPhone and iPad. I’m going to talk about a very simple program I wrote in Swift 1.1 using Xcode 6.2 that reads all the barcodes mentioned in my last post.

As simple as the app is, it uses several technologies that can start to get to get complicated. Fortunately that isn’t the case in this program. Specifically, AVFoundation, Grand Central Dispatch, and Segues are used. AVFoundation has the barcode reading functionality. GCD is used to manage threads. Segues are used programmatically to switch from the scanner view and the data display view.

HelloUPC barcode reader project. I think you’ll like the license.

The project starts out as a single view iOS application. There was no reason to make it iPhone only so it is a universal app. Now is the part of the blog where I wonder how much code I should bother to explain when you can just read it. Although I’m not big on code comments. So I should explain somethings perhaps. To make it easier on me, I’m going to assume you have some familiarity with the AVCam demo code (written in Objective-C) by Apple. The demo code is available from the Xcode documentation.

The important file in my project is ViewController.swift. What a surprise. That is a template file generated when creating the project. It’s the initial view controller that starts up when the app is launched. A view controller needs a view. That is defined in the CameraView.swift file. Things are kept extra simple by not having any controls in this view.

To get things rolling, it is necessary to setup the camera. When the view is loaded, the checkDeviceAuthorizationStatus() function is called. This packages up several procedures in one call:

  1. Request access to the rear camera.
  2. Configure the camera on a session thread that is defined in the AppDelegate.swift file.
  3. As part of the configuration, setup a metadata collection object that reads the barcodes.

 

All these things are done in Swift rather than Objective-C of course. And I also threw in my own ad hoc code style. Step 3 above is in this code snippet from the configure() function I use to setup the capture session.

            if captureSession.canAddOutput(metaDataOutput) {
                captureSession.addOutput(metaDataOutput)
                metaDataOutput.metadataObjectTypes =
                    metaDataOutput.availableMetadataObjectTypes.filter() {
                        $0 as NSString != "face"
                }
                metaDataOutput.setMetadataObjectsDelegate(self, queue: sessionQueue)
            }

 

The metaDataOutput object was defined at the top of the ViewController class. There is also a delegate set. The view controller is the delegate. It has to follow the AVCaptureMetadataOutputObjectsDelegate protocol. Only one function needs to be implemented for that protocol which is the captureOutput() function.

The work is done by the framework. It is still necessary to do something in the captureOutput() function. That’s called when the camera session “sees” one of the barcodes it recognizes. It gets passed the data which is then used to segue over to the display view where you can see the type of code plus the data from the code.

The code view only has labels and a button. The button segues you back to the scanner view to start over.

I didn’t write this code to be a stand alone app. I wrote it to learn how to read codes and do something useful with them. In this case, I simply display the values. This was also the first time I’ve used segues. It’s also the first time I’ve read barcodes.

The performance of the app is only so so. At least the debug version is. Some codes won’t read or take a while to get recognized on my iPhone 5s. Lighting seems to make a difference. Viewing angle doesn’t seem to be a huge issue. With the EAN-13 codes, it sometimes helps to get the code at a slight angle. I tried to read a printed stamp on an envelope. It took a while for the code to recognize the type of code. But no data was displayed. The code assumes the value will be a string.

There were also small barcodes of some type on some apples (the fruit). The iPhone 5s was not able to read them. There are some other codes that don’t seem to read well. There are also a surprising number of codes that do read well. The QR codes and DataMatrix codes have a lot of data. They can be fun.

I’m not sure what comes next.

I hope it’s good.

 

Using GitHub For Xcode Source Control

Source code versioning starts to become important with even modest sized projects. While you can use Xcode’s code snapshot feature, setting up a git repository is much better. If you’re a lone programmer working on a project, it is trivial for you to create a local git repository. This article isn’t about that. You can also use OS X Server as a git repository. This is something an organization might want to do. This article isn’t about that either.

Setting up a GitHub repository is a little trickier than I expected. The Xcode documentation is all about using OS X Server or just a local git repository. I did some experimentation and found a way to setup GitHub in a nearly pain free way. There is more than one way to do it. I’m going with a method that works for both existing projects and new projects. Hopefully someone reading this will be able to provide a completely pain free method.

Step one: create a GitHub account. This is pretty easy. I’m currently using a free account, so I can’t do private/hidden repositories. This is perfectly fine for open source projects. GitHub also has a nice little feature where you can tell other users that you are looking for a job. Having code out there shows what you can do.

It’s a good idea to create your account with Safari and let Safari create your password. This gets the password onto your keychain where you can retrieve it later as needed.

Step two: create a GitHub repository for your project. It doesn’t matter if you are creating the repository for an existing project or a brand new one. Use the name of your project for the repository. Try to avoid using spaces. It may not matter, but GitHub will turn them into hyphens.

When you have created your repository, it should look something like this.

Creating a GitHub repository
Creating a GitHub repository

Once you’ve created the repository, you will get a screen like this.

Created Repository
Created Repository

Copy the URL where it says, “HTTPS clone URL”. You will need that for the next step.

Step three: open Xcode. Go to the Source Control menu and choose Check Out… . You will paste the URL for your repository in the checkout dialog that follows.

Checkout Dialog
Checkout Dialog

The first time you do this, you will have to enter your GitHub credentials into Xcode. Let it always allow so that it remembers. That way you don’t have to dig up your password from Key Chain every time you start a new project.

Since we are creating a new project or adding an existing project to GitHub, be sure to choose a directory other than where your project will be. This will become clear later. Do not check the “Source Control” box when you create your project. If you do, don’t panic. You will be replacing the .git directory anyway.

Step four: Create your project in Xcode if you don’t already have one. If you have a project, skip this step. Place the project where you want it. As I said above, make sure that is a different location than you did the checkout. Files getting overwritten is rather inconvenient.

Step five: Open Terminal. This is the part I wish was a little better integrated into Xcode. Never fear though. You are a programmer! This should be comfortable for you. You want to cd to the directory that you did the checkout. You will know you’re there when the following works.

Triton:Foo david$ ls -la
total 32
drwxr-xr-x+  8 david  staff   272 Mar  7 03:14 .
drwx------+ 39 david  staff  1326 Mar  7 03:21 ..
-rw-r--r--@  1 david  staff  6148 Mar  7 03:13 .DS_Store
drwxr-xr-x+ 15 david  staff   510 Mar  7 03:29 .git
-rw-r--r--+  1 david  staff    76 Mar  7 03:15 .gitignore

Don’t worry. I know you don’t have a .gitignore file yet. You will create that now. I prefer to use vim when creating a text file.

Triton:Foo david$ vim .gitignore

You really should have a basic understanding of vim and the shell. Fortunately, what you have to do isn’t so hard. Never be afraid of the command line. The command line is user friendly. It’s just picky about who it’s friends are. However you care to go about it, make sure your .gitignore file contains at least the following lines. You may wish to add others later. You may also chose to download someone else’s .gitignore if you find it more useful for your situation.

.DS_Store
*.xcodeproj/xcuserdata
*.xcodeproj/project.xcworkspace/xcuserdata

Every OS X directory has a .DS_Store. You don’t want to be adding that to GitHub. The second two lines make sure that your personal information that ends up in Foo.xcodeproj (whatever the name of your project file is) doesn’t get added to GitHub. The reason for using Terminal for all this is that dot files (hidden files) do not show up in Finder. The reason for checking out the project from GitHub is to have the contents of the .git directory properly configured for GitHub.

Next, you move your .git and .gitignore over to your project directory. For example (on one line)

Triton:Foo david$ mv .git .gitignore /Users/david/XcodeProjects/Foo

Then cd to that directory and you should see something like the following.

Triton:Foo david$ ls -la
total 32
drwxr-xr-x+  8 david  staff   272 Mar  7 03:14 .
drwx------+ 39 david  staff  1326 Mar  7 03:21 ..
-rw-r--r--@  1 david  staff  6148 Mar  7 03:13 .DS_Store
drwxr-xr-x+ 15 david  staff   510 Mar  7 03:29 .git
-rw-r--r--+  1 david  staff    76 Mar  7 03:15 .gitignore
drwxr-xr-x+  4 david  staff   136 Mar  7 03:11 Foo
drwxr-xr-x+  5 david  staff   170 Mar  7 03:09 Foo.xcodeproj
-rw-r--r--+  1 david  staff    28 Mar  7 03:08 README.md

Step six: This should be the last thing you need to do in the shell. Add the files to the repository, commit, and push. The push step will require your GitHub credentials.

Triton:Foo david$ git add .gitignore
Triton:Foo david$ git add ./*
Triton:Foo david$ git commit -m 'Add .gitignore and project files'
Triton:Foo david$ git push
warning: push.default is unset; its implicit value has changed in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the traditional behavior, use:

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

  git config --global push.default simple

When push.default is set to 'matching', git will push local branches
to the remote branches that already exist with the same name.

Since Git 2.0, Git defaults to the more conservative 'simple'
behavior, which only pushes the current branch to the corresponding
remote branch that 'git pull' uses to update the current branch.

See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)

Username for 'https://github.com': DavidSteuber
Password for 'https://DavidSteuber@github.com': 
Counting objects: 13, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (13/13), 3.41 KiB | 0 bytes/s, done.
Total 13 (delta 0), reused 0 (delta 0)
To https://github.com/DavidSteuber/Foo.git
   1925a59..332395f  master -> master

At this point, your project should now be in GitHub’s source control and you should be able to add files and commit changes from Xcode’s Source Control menu. Committing and pushing are two separate operations. Xcode lets you check a box called “Push to remote” when you are committing changes and will do the push for you. Until you actually do push your changes, they do not show up on GitHub.

I hope this article proves useful. I would be grateful for any feedback. Yes, I do require registration to leave comments. This is really a spam prevention measure. I do not collect e-mail addresses or anything like that. Just use a password you don’t use anywhere else. I use HTTPS for everything.

Code long and prosper.

Apple's MusicCube example project  on GitHub
Apple’s MusicCube example project on GitHub
Apple's MasicCube Code Example in Xcode
Apple’s MusicCube Code Example in Xcode

Epilogue. Ray Wenderlich has a different and more detailed method of setting up Xcode with GitHub: How To Use Git Source Control with Xcode in iOS 6.