Setting up geofences

Sometimes, your app doesn't really need to know the details of the user's whereabouts. Sometimes, you're only interested in tracking whether the user has exited or left a certain area, in order to show certain content in your app or to unlock some kind of special feature. Core Location has great support for monitoring geofences. A geofence is a certain area that is defined using a certain GPS coordinate and a circular radius around this point. In Core Location, geofences are set up using CLRegion subclasses. Core Location provides two different region types that you can use:

  • CLCircularRegion
  • CLBeaconRegion

A CLCircularRegion type is used to set up a geofence, as described before. A CLBeaconRegion type is used with physical BLE iBeacons, and essentially provides geofencing in a very small radius, for instance, just a couple of meters. In this section you will learn how to set up a CLCircularRegion type that is set up around a user's first detected location. Setting up geofencing, or region monitoring, with both types of regions is very similar so all principles for monitoring a circular region also applies to beacon regions.

If you look at the GeofenceViewController, you'll notice that it has a button labelled Set Geofence. The @IBAction for this button does quite a lot of the work already, but one key element is missing—it doesn't inform the location manager about the region that should be monitored. Add the following code to the end of setGeofence() in GeofenceViewController:

let region = CLCircularRegion(center: location.coordinate, radius: 30, identifier: "current-location-geofence")
locationHelper.setGeofence(at: region, exitHandler, enterHandler)

The preceding code uses the location that was obtained from the user before, and uses it to create a circular region with a radius of 30 meters. The identifier that is passed to the region should be an identifier that uniquely defines the region. If you reuse an identifier, Core Location will stop monitoring the old region with that identifier, and will monitor the new region instead. For the LocationServices app, this is perfect, but if you want your app to observe multiple regions, you must make sure every region has its own unique identifier.

Next, add the following implementation for setGeofence(at:_:_:) to the LocationHelper:

func setGeofence(at region: CLRegion, _ exitHandler: @escaping () -> Void, _ enterHandler: @escaping () -> Void) {
  guard CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self)
    else { return }

  geofenceExitCallback = exitHandler
  geofenceEnterCallback = enterHandler
  locationManager.startMonitoring(for: region)
}

The preceding method is again very similar to the other location helper methods. Let's move right on to implementing the CLocationManagerDelegate methods that the location manager will call:

func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
  geofenceEnterCallback?()
}

func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
  geofenceExitCallback?()
}

The preceding two methods are part of the CLocationManagerDelegate protocol, and are called when a user enters or exits a certain area. Since there's no extra work to be done by the helper, the corresponding callbacks are immediately called so the GeofenceViewController can update its interface accordingly.

Try opening the app and tapping the Set Geofence button. An orange circle should now appear on the map to visualize the geofence you have set up. If you exit or enter the region, the status label should update accordingly, to show whether you have just entered or left the geofence. Note that it might take up to five minutes for iOS to properly register, monitor, and report updates about your geofence. Note that your user should have an active internet connection for region monitoring to work optimally.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.239.148