Location Notifications with UNLocationNotificationTrigger
Learn how to use UNLocationNotificationTrigger to set up location-triggered notifications for your iOS app. By Graham Connolly.
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
Location Notifications with UNLocationNotificationTrigger
30 mins
- Getting Started
- What Is Core Location?
- Setting Up Core Location
- Creating a Geofence
- Placing an Order
- Monitoring User Location
- Location Authorization
- Requesting Location Authorization
- Triggering a Location Notification on Arrival
- Notification Authorization
- Using UNLocationNotificationTrigger to Notify the User
- Handling Notification Action
- Simulating User Movement
- Connecting to a physical device
- Simulating the Journey
- Handling a Geofence Entry Event
- Alerting the Kitchen
- Getting Background Updates
- Where to Go From Here?
Handling Notification Action
You’re almost there! To handle notifications and their actions, you need to add UNUserNotificationCenterDelegate
.
Open LocationManager.swift, and add the following extension after the LocationManager
class:
extension LocationManager: UNUserNotificationCenterDelegate {}
This extension allows LocationManager
to act as the UNUserNotificationCenter
‘s delegate.
With the delegate set up, add the following code inside LocationManager
, beneath the properties:
// 1
override init() {
super.init()
// 2
notificationCenter.delegate = self
}
This code:
- Overrides the initializer of the
NSObject
to provide custom initializer code. - Configures
LocationManager
to be adelegate
ofnotificationCenter
.
Next, add these delegate methods inside the extension
:
// 1
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
// 2
print("Received Notification")
// 3
completionHandler()
}
// 4
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler:
@escaping (UNNotificationPresentationOptions) -> Void
) {
// 5
print("Received Notification in Foreground")
// 6
completionHandler(.sound)
}
Here’s an overview of the code:
- This delegate method will be called if the user taps on the notification.
- Prints to the debugger when you receive a notification.
- Tells the system you finished handling the notification.
- This delegate method handles a notification that arrives when the app is in the foreground.
- Prints to the debugger when you receive a notification in the foreground.
- Tells the system that you’ve finished handling the foreground notification and it should only play a notification sound, not display the notification.
With this code added, you can now test out your location notifications.
Simulating User Movement
Unless you’re lucky enough to live near Apple Campus, where the fictional Swifty TakeOut is, you’ll need to simulate entering the region. To do this, you’ll need to add a .gpx file. GPX, or GPS Exchange Format, is an XML file used to describe waypoints, tracks and routes:
- Go to the Project navigator.
- Right-click the Swifty TakeOut group.
- Click New File….
- Select GPX File.
- Name it SimulatedLocations.
- Click Create.
With SimulatedLocations.gpx added, replace its contents with the following:
<?xml version="1.0"?>
<gpx version="1.1" creator="Xcode">
<wpt lat="37.422155" lon="-122.134751">
<name>Apple Park</name>
<time>2021-01-23T14:00:00Z</time>
</wpt>
<wpt lat="37.33182000" lon="-122.03118000">
<name>Apple Campus</name>
<time>2021-01-23T14:00:05Z</time>
</wpt>
</gpx>
Here, you’ve added an XML file that contains two waypoints: Apple Park and Apple Campus. You’ll notice that each waypoint has a timestamp. They’re five seconds apart, simulating a five-second journey from Apple Park to Apple Campus.
With the GPX file added, you can start simulating an entry event.
Connecting to a physical device
Unfortunately, simulating UNLocationNotificationTrigger
doesn’t appear to work well in the simulator. But, it does work on a physical device hooked up to Xcode. To follow the steps in this section, you’ll need to connect an iOS device to your computer with a USB cable.
On the connected device, you’ll see a notification asking if you want to trust the computer:
Tap Trust.
Next you’ll need to set the developer team for your project:
- In Xcode, select the project from the Project navigator.
- Click the SwiftyTakeOut app target.
- Select the Signing & Capabilities tab.
- Select your developer account from the Team drop-down control in the Signing section.
You’re ready to install the app on your device. Use the Scheme menu to set the active scheme to your connected device:
Build and run.
Xcode will install the app on your device and try to open it. When Xcode tries to open the app, it will probably show an error due to security restrictions:
To fix the error, open the Settings app on your physical iOS device. Navigate to General ▸ Device Management ▸ Apple Development: [account]:
Tap Trust “Apple Development: [account]”.
A notification will appear. Tap Trust to confirm.
Once your developer account has been trusted and your app has been verified, Xcode is ready to be able to launch the app.
With your iOS device unlocked, build and run from Xcode. The app should open on the physical device:
Woohoo! You’re ready to proceed with the rest of this tutorial.
Simulating the Journey
Now you’re ready to try the simulated locations in the GPX file you added.
Build and run on your connected iOS device. When the app launches, select an item from the menu, place an order and tap Yes to get notified:
Notifications will appear asking permission: Tap Allow While Using App for location and Allow for notifications.
Next, switch back to Xcode, select the Location icon in the Debug bar and choose SimulatedLocations:
Your simulated journey will now start. After five seconds or so have passed, you’ll see the following in the debugger:
The output gets printed when your app is in the foreground and userNotificationCenter(_:willPresent:withCompletionHandler:)
in LocationManager.swift is called.
Next, either stop the app in Xcode and build and run the app again, or stop simulating the location. Now place a new order and tap Yes to get notified. Then, before simulating the user journey, put the app in the background by either locking the screen or going to the Home screen. Once the app is in the background, simulate your journey. You’ll now see a local notification appear:
If you tap the notification, it’ll launch the app and print the following to the debugger:
The difference here is that if your app is in the foreground, you won’t see the notification, but if it’s in the background, then you’ll see it.
Congratulations, your app now notifies you when you enter the region! But your journey isn’t over yet!
Printing to the debugger on arrival is cool, but wouldn’t it be great if your user is also alerted?!
In the next section you’ll improve the user experience by:
- Showing an alert when the app is in the foreground.
- Showing an alert when the app gets launched by tapping a notification.
Handling a Geofence Entry Event
In this section, you’ll show an alert to the user if the app is in the foreground when the geofence is entered. Finally, a local notification will wake the app when in the background.