Geofencing with Core Location: Getting Started
In this geofencing tutorial, you’ll learn how to create and use geofences in iOS with Swift using the Core Location framework. By Michael Katz.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Geofencing with Core Location: Getting Started
30 mins
- Getting Started
- Do You Know the Way to San Jose?
- Say Hi to Tim
- Setting Up Core Location
- Location Permissions
- Showing the User’s Location
- Registering the Geofences
- How Geofencing Works
- Creating Regions
- Monitoring Regions
- Adding Geotifications
- Removing Geotifications
- Reacting to Geofence Events
- Handling Location Errors
- Handling Location Events
- Comings and Goings
- Simulating Location Events
- Going on an Imaginary Drive
- Notifying the User of Geofence Events
- Building the Notification
- Where to Go From Here?
Geofencing notifies an app when its device enters or leaves configured geographical regions. For example, it lets you make cool apps that can trigger a notification when you leave home or greet users with deals whenever their favorite shops are nearby.
In this geofencing tutorial, you’ll learn how to use the Region Monitoring API from Core Location. More specifically, you’ll cover how to:
- Set up Core Location and permissions
- Register your geofences
- React to geofence events
- Notify users of geofence events
To do this, you’ll create a location-based reminder app called Geotify that will let users create reminders and associate them with real-world locations.
Getting Started
Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.
The starter project provides a simple user interface for adding and removing annotation items to a map view. Each annotation item represents a reminder with a location, called a geotification.
Build and run the project, and you’ll see an empty map view.
The app is set up for users to start adding their geotifications right away.
Do You Know the Way to San Jose?
Tap the + button in the navigation bar to add a new geotification. The app will present a separate view, allowing you to set up various properties for your geotification.
For this tutorial, you’ll add a pin to Apple Park in Cupertino. If you don’t know where it is, open this map and use it to find the correct spot. Be sure to zoom in to make it accurate!
This is what the map will look like once you zoom and drag to the correct spot in Cupertino.
Say Hi to Tim
The Radius represents the distance (in meters) from the specified location where iOS will trigger the notification. The Note can be any message the user wishes to display as part of the notification. The app also lets the user specify — via the segmented control at the top — whether the reminder should be triggered upon entry to or exit from the defined circular geofence.
Enter 1000
for the radius value and Say Hi to Tim! for the note, and leave the top switch at Upon Entry for your first geotification.
Click + once you’re satisfied with all the values. You’ll see your geotification appear as a new annotation pin on the map view, with a circle around it denoting the defined geofence:
Tap the pin and you’ll reveal the geotification details you set earlier. Don’t tap the trash button unless you want to delete the geotification!
Feel free to add or remove as many geotifications as you want. Since the app uses UserDefaults
as a persistent store, the list of geotifications will persist between launches.
Setting Up Core Location
At this point, any geotifications you’ve added to the map view are only visual; you won’t actually receive any notifications. You’ll fix this by taking each geotification and registering its associated geofence with Core Location for monitoring.
But before any geofence monitoring can happen, you need to set up a CLLocationManager
and request the appropriate permissions.
Open GeotificationsViewController.swift and add the following after the geotifications
declaration:
lazy var locationManager = CLLocationManager()
This sets up an instance variable to store the location manager. Using lazy
means the initial value isn’t calculated until the first time it’s used.
Next, replace viewDidLoad()
with the following code:
override func viewDidLoad() {
super.viewDidLoad()
// 1
locationManager.delegate = self
// 2
locationManager.requestAlwaysAuthorization()
// 3
loadAllGeotifications()
}
Here’s an overview of what you do in the code above:
- Set the view controller as the
delegate
of thelocationManager
so that the view controller receives the relevant delegate method calls. - Call
requestAlwaysAuthorization()
, which displays a prompt to the user requesting authorization to use location services Always. Apps with geofencing capabilities require Always authorization since they must monitor geofences even when the app isn’t running. - Call
loadAllGeotifications()
, which deserializes the list of geotifications saved toUserDefaults
and loads them into the localgeotifications
array. The method also adds the geotifications as annotations on the map view.
Location Permissions
There are four levels of location permissions the user can grant your app:
- Don’t Allow: The user has refused location access.
- Allow Once: The user will allow your app to determine location just once.
- Allow While Using App: Your app can determine location whenever the app is in the foreground.
- Always Allow: Your app will receive location updates when in the background and be able to determine location in the foreground.
To protect your users’ privacy, even if you request Always permission, the app will only prompt for Allow While Using App in the first instance. This will give you provisional access to background locations, and at some point later on, when a background location event happens, the user will be asked to confirm that they want to continue to allow background location access.
This confirmation will happen at a time outside of your control, and probably when your app is not in the foreground. For this reason, it’s important to clearly explain why you need location access at all times. You do this in Info.plist, under the NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription keys. Without these values, your app won’t request location access. Without a good explanation, the user may reject location permissions. The starter project already contains values for both keys.
Build and run. You’ll see a user prompt with the description taken from Info.plist:
Tap Allow While Using App, as discussed above. Make sure Precise is still On.
Showing the User’s Location
Before implementing geofencing, there’s a small issue you have to resolve: The user’s current location isn’t showing up on the map view! By default, the map view disables this feature, and as a result, the zoom button on the top-left corner of the navigation bar doesn’t work.
Fortunately, the fix isn’t difficult — you’ll enable the current location after the user authorizes the app.
In GeotificationsViewController.swift, find the CLLocationManagerDelegate
extension and add the following code:
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
// 1
let status = manager.authorizationStatus
// 2
mapView.showsUserLocation = (status == .authorizedAlways)
// 3
if status != .authorizedAlways {
let message = """
Your geotification is saved but will only be activated once you grant
Geotify permission to access the device location.
"""
showAlert(withTitle: "Warning", message: message)
}
}
This method is called whenever the location authorization status changes and also when the location manager is first created. This implementation does the following:
- Retrieves the authorization status from the manager.
- Shows the user location when
authorizedAlways
, which is the only mode useful for this app. - If the user hasn’t authorized the app, it displays a message alert.
showAlert(withTitle:message:)
is a helper method in Utilities.swift that takes a title and message and displays an alert view.
Build and run. If you’re running the app on a device, you’ll see the location marker appear on the main map view. If you’re running on the simulator, click Features ▸ Location ▸ Apple in the menu to see the location marker:
The zoom button on the navigation bar now also works. :]