Location Notifications with UNLocationNotificationTrigger

Learn how to use UNLocationNotificationTrigger to set up location-triggered notifications for your iOS app. By Graham Connolly.

4.9 (7) · 1 Review

Download materials
Save for later
Share
You are currently viewing page 3 of 4 of this article. Click here to view the first page.

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:

  1. Overrides the initializer of the NSObject to provide custom initializer code.
  2. Configures LocationManager to be a delegate of notificationCenter.

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:

  1. This delegate method will be called if the user taps on the notification.
  2. Prints to the debugger when you receive a notification.
  3. Tells the system you finished handling the notification.
  4. This delegate method handles a notification that arrives when the app is in the foreground.
  5. Prints to the debugger when you receive a notification in the foreground.
  6. 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:

  1. Go to the Project navigator.
  2. Right-click the Swifty TakeOut group.
  3. Click New File….
  4. Select GPX File.
  5. Name it SimulatedLocations.
  6. 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:

Screenshot Trust This Computer Notification

Tap Trust.

Next you’ll need to set the developer team for your project:

  1. In Xcode, select the project from the Project navigator.
  2. Click the SwiftyTakeOut app target.
  3. Select the Signing & Capabilities tab.
  4. Select your developer account from the Team drop-down control in the Signing section.

Screenshot Xcode Developer Team

You’re ready to install the app on your device. Use the Scheme menu to set the active scheme to your connected device:

Screenshot Xcode active scheme

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:

Screenshot Xcode could not launch app

To fix the error, open the Settings app on your physical iOS device. Navigate to General ▸ Device Management ▸ Apple Development: [account]:

Screenshot Settings Apple Developer Trust

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:

The Swifty TakeOut menu with an overview of options for ordering

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:

App screenshot notification

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:

Selecting a custom location

Note: Sometimes the Location icon doesn’t appear on the Debug bar. If this happens, stop debugging and build and run the app again.

Your simulated journey will now start. After five seconds or so have passed, you’ll see the following in the debugger:

Arrived at TakeOut - Foreground

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:

Local Notification

If you tap the notification, it’ll launch the app and print the following to the debugger:

Received Notification

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!

Blue-haired person in the driver seat of a car, singing, while a bird flies outside

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:

  1. Showing an alert when the app is in the foreground.
  2. 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.