Writing an iBeacon App in Swift

| | 0 Comments| 10:37 AM
Categories:

Editor’s Note: This is Part Two of our series of articles on creating a Swift iBeacon application. By the end of the series you will have written a “game” in Swift called You’re Getting Warmer! which allows you to track down and find a beacon. Part One gets you up and running iBeacon with a Gimbal Proximity Beacon Series 10.

Before getting started with Part Two, you should have an operating iBeacon and know its UUID. If you don’t have an iBeacon start with Part One of this series!

If you’re working with iBeacon we’re just going to assume you known how to create a new Single View Application Swift project with Xcode. Go ahead and do that now. We named our project gettingwarmer.

gettingwarmer_xcodeproj

Beacon Ranging

There are two methods of listening for iBeacons in iOS: monitoring and ranging. The difference between the two is that monitoring is an activity that can continue running in the background, while ranging is a foreground activity. Radius Networks wrote up a nice explanation describing the differences in detail. Apple’s iBeacon documentation uses the term ranging to describe the activity of determining the proximity of a given iBeacon. Our first application will make use of ranging as opposed to monitoring.

BeaconManager

I have always preferred to use the singleton “manager” pattern for working with CoreLocation in iOS. We’ll create a class called BeaconManager which will be responsible for an instance of CLLocationManager as well as serving as our CLLocationManager delegate. To get started create a new file BeaconManager.swift in your gettingwarmer Xcode project and add the following implementation:

The class declaration and init routine should be self-explanatory. If you haven’t been working with Swift 1.2 you may have missed the introduction of the static keyword which allows for a quick implementation of the singleton pattern.

Let’s first implement the didChangeAuthorizationStatus method, because once we are authorized we want to start ranging.

Here’s our implementation:

If the OS can’t determine the authorization status (.NotDetermined), we’ll simply ask for it again (why not).

If we receive a callback that our status is .AuthorizedWhenInUse (what we requested) or .AuthorizedAlways (which will never be the case), we’ll call our startRanging method.

If on the other hand we receive .Denied or .Restricted, we’ll broadcast a notification with NSNotificationCenter that will be heard by our ViewController. The ViewController will then be responsible for raising a dialog indicating that location services are required for the app to operate properly.

Now, let’s take a look at our startRanging method.

Ranging begins with the startRangingBeaconsInRegion method, and in our case a region is identified as “being in the proximity of a beacon broadcasting a UUID of 788FA98B-871C-4C71-9944-88ADEC84A8DA”. It’s that simple. If iOS hears a beacon with this UUID, it is “in” that region.

It may be confusing at first that a “region” in this context is not geographical. Apple’s QuickHelp documentation explains it this way: “A CLBeaconRegion object defines a type of region that is based on the device’s proximity to a Bluetooth beacon, as opposed to a geographic location.

Once ranging starts we have to be prepared to receive didRangeBeacons calls on our CLLocationManager delegate. For now, we’ll add this implementation:

Before leaving ranging, it is important to draw the distinction between monitoring for regions and ranging beacons. Monitoring can run in the background with notifications sent to your app when the registered CLBeaconRegion is “entered” (that is, the beacon was heard). Ranging is for finer proximity detection and can only be used while the application is in the foreground. Again, reading the Radius Networks article is useful.

Rounding Out

Thus far we’ve implemented:

  • a BeaconManager class capable of requesting location services authorization
  • the didChangeAuthorizationStatus method to handle changes in location services authorization from the user
  • a startRanging method which will start listening for our iBeacon
  • the didRangeBeacons method which will be called when iOS hears our iBeacon

We have a few more things to do before running the application:

  • setting NSLocationWhenInUseUsageDescription in our Info.plist
  • creating an instance of the BeaconManager when our ViewController appears
  • intercepting LOCATION_DENIED notifications in the event the user declines location services authorization

In your Info.plist, create a new key called NSLocationWhenInUseUsageDescription like so:

infoplist

Next, round out the ViewController code by adding the following:

When our view appears we want to create an instance of the BeaconManager which in turn will request authorization. Therefore we add our ViewController as an NSNotification observer for the LOCATION_DENIED notification. If this notification is received we pop up an alert dialog (UIAlertController) indicating that location services permission is required.

Run It!

If you’ve implemented everything you should now be able to run the application on your iOS device (note: this will not work in a simulator). After granting location services authorization and bringing out our iBeacon we see in the console:

[objc]
Beacon ranged: CLBeacon (uuid:<__NSConcreteUUID 0x1702224e0> 788FA98B-871C-4C71-9944-88ADEC84A8DA, major:1, minor:0, proximity:2 +/- 0.68m, rssi:-59)
[/objc]

What Could Possibly Go Wrong?

Software development can be rewarding and a lot of fun, but it can also drive you crazy when things don’t work right. In this series there are a lot of things that could go wrong that would prevent iOS from recognizing your beacon. If you’re having trouble, consider:

  • is your iBeacon programmed with the same UUID as your CLBeaconRegion?
  • is your iBeacon powered?
  • was the app granted location services permission?
  • is the iBeacon in range?
  • is Bluetooth enabled on your iOS device?

Getting the Code

The complete source code for this tutorial is available on BitBucket. The implementation for this article is available on the partTwo branch.

Next Up

We can now receive iBeacon messages in our application, but we aren’t doing anything with the information. In Part 3 of this series we’ll go through the various properties of the CLBeacon class, namely:

  • proximity
  • accuracy
  • rssi

We’ll then begin adding a user interface to our view controller for a nice game of You’re Getting Warmer!. Stay tuned!

Leave a Reply

Your email address will not be published. Required fields are marked *