kodeco.com Forums

iBeacon Tutorial with iOS and Swift

Learn how you can find an iBeacon around you, determine its proximity, and send notifications when it moves away from you.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/632-ibeacon-tutorial-with-ios-and-swift

Thanks for your cool tutorial … unfortunately there’s a problem:
Adding a beacon device UUID works perfect and saving the beacon to UserDefaults is also fine. But after restarting the app, the loadItems() function loads the beacon stored before but doesn’t locate it. When I delete the table row and re-add the same beacon, it’ll be located again.
I’ve tried to add a startMonitoring(items.first!) call in viewDidLoad() of the ItemsViewController. Now the
locationManager(_ manager: CLLocationManager,
didRangeBeacons beacons: [CLBeacon],
in region: CLBeaconRegion)
gets called, but the beacons array is passed in as an empty array.

Any idea, why the location updates don’t work after app restart?

Does your func loadItems() have the line of code:
startMonitoringItem(item)
inside the loop?

No, slightly different - the following after the loop:
if items.count > 0 {
startMonitoring(items.first!)
}

I noticed, that had to restart the beacon to fire up the location update in your app. I got it working.

… now I added an observer for .UIApplicationWillEnterForeground notification to ItemsViewController which reloads the table data. This was necessary to update the items if they did change their operation during your app being in the background.

I’m curious to know if you have the same issue if you use the Final project download zip from the tutorial.

I’m sure you know, but the code you posted will only start monitoring the first beacon in the list. If you have other UUIDs in the UserDefault list, then only the first one will be monitored.

Oops, I really overlooked adding the startMonitoringItem(item) line at the right place inside loadItems(). Now it seems to work fine … also w/out the observer. Sorry!

No prob. Glad its working for you.

I’m getting
Extensions may not contain stored properties
under

// MARK: - CLLocationManagerDelegate
extension AppDelegate: CLLocationManagerDelegate {
    var locationManager = CLLocationManager()
}

Hi efwjames,
Its because you are trying to declare the locationManager property inside the extension (as the error indicates). Move it to the main AppDelegate class, just below var window: UIWindow?.

Owen

Great Tutorial Owen… is there any way to get the BLE MAC Id? I’ve seen some iOS apps that display it…

Hi vijaymys,
When a BLE device is first discovered by Core Bluetooth, it assigns an identifier to it. This identifier will be unique (and constant) for that particular BLE device for that particular iOS device. Its not technically the MAC address of the BLE device. In all my BLE projects, I use the identifier for normal distinctions between BLE units.

Accessible via :peripheral.identifier

I don’t believe the identifier will be the same across all iOS devices for the same BLE device. Not sure about this as I haven’t tested it.

If your project has a need for knowing the ‘actual’ MAC address, then I suggest one of the following:

  • add a GATT Characteristic (called MacAddress or something :slight_smile: on the BLE firmware and read the MAC value once a live Bluetooth connection is made.
  • OR, if the MAC address needs to be known before a live connection is made, then put it in the advertising packet of the BLE module
    Of course, both of these suggestions assume that you are also designing the BLE firmware.

Hope this helps,
Owen

Thanks for the super quick reply…will try your suggestions out…

Thanks for your tutorial. I followed it but I am unable to detect the beacons.
When debugging locationManager(_ manager: CLLocationManager,
didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion), the beacons array is always empty.
I am using XCode 8.3.2 and an iPad 4th gen with IOS 10.3.2.
Did the same in Android with the UUID and I can see them.
Am I overlooking something?

Hi,

Thanks for your tutorial.

I have the same problem as nfilipe with iPhone 5S,
Did you find any solution for this issue ?

Thanks

Hi nfilipe & samosrfist,

Can you set a break point and ensure that startMonitoringItem is being called?
Also, the basic checks like Bluetooth enabled, permissions granted for Bluetooth data usage, etc.
Did you try downloading the finished project and running it with no code changes?

Owen

Yes, it is being called.
Running the downloaded finished project and adding the proximity id of the beacon shows the empty array on the didRange func.
Bluetooth is enabled and the Location permission of the app is set to always.
Tried uninstalling other beacon apps i had installed with the same region as well.

What method did you use to find the UUID? i.e. beacon document or another ibeacon app?
Also, which ibeacon is it? I recently bought one that shows up as a Bluetooth device, but not a beacon… basically worthless.

On you iPhone, did it show up on other beacon apps?

Hi,

Thank you for your reply.
On my application the code is well called and the permissions are good.
I use beacons whose udid worked on iOS 9
To find udid i use the application of the manufacturer

Thank you for your help

It’s a Jaalee beacon. I have developed an app for android that uses them.
Was trying to do the same with the ipad.
I used the UUID that comes with the documentation of the manufacturer and on my android phone it also shows on other beacon apps.
On the ipad installed the “Locate Beacon” app that does not show them. But i have another app that sees them…