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 2 of 4 of this article. Click here to view the first page.

Location Authorization

Your app can request two categories of location authorization:

  1. When in Use: Your app can use location services when it’s running in the foreground. With the help of background modes, the app can also get updates in the background.
  2. Always: Your app can use location services whenever it needs to. If the app isn’t running, the system will wake it up to deliver the event. There’s no need for background modes with this permission.

It’s important to respect your user’s privacy and use When in Use as much as possible. Swifty TakeOut‘s core functionality isn’t location based, so you shouldn’t use the Always permission.

It’s also important to explain to the user why their location needs to get monitored. Many developers prompt for location permission when the user first opens the app. That can be overwhelming for the user since they don’t understand why the app needs their location. Instead, consider asking for user’s permission when they actually want to use the location functionality. For example, your app will request permission when a user taps on Yes to get notified on arrival. The app will also explain in the permission prompt the reason that the app needs the location.

To do this, open Info.plist and add the Privacy – Location When In Use Usage Description key. In raw mode, this is the NSLocationWhenInUseUsageDescription:

Adding NSLocationWhenInUseUsageDescription to Info.plist

For the value, add the string Swifty TakeOut uses your location to check you in on arrival:

Setting the description text

Note: Without the required key-value pair, you’ll be unable to get the user’s location.

Requesting Location Authorization

Now that you’ve added the required key-value pair for location permissions, it’s time to ask the user. Back in LocationManager.swift, inside validateLocationAuthorizationStatus(), locate case .notDetermined, .denied, .restricted. You’ll request the WhenInUse permission here.

Below print("Location Services Not Authorized"), add:

locationManager.requestWhenInUseAuthorization()

With this added, you can now request the user’s permission.

Build and run. You should now see the location authorization dialog the first time an order is placed:

Location authorization dialog

As shown in the screenshot above, there are three categories of responses the user can give:

  1. Allow Once: The user will allow your app to use their location once.
  2. Allow While Using App: The user has given permission to use their location whenever the app is being used. In general, this means the app is in the foreground. However, this permission can include when the app is in the background, suspended or terminated.
  3. Don’t Allow: The user refuses permission.

Tap Allow While Using App.

Triggering a Location Notification on Arrival

You want to alert the user on arrival at Swifty TakeOut. To do this, you’ll create a special type of notification: UNLocationNotificationTrigger. This object creates a local user notification when the device enters or exits a region. Because you configured the geofence region earlier in this tutorial, you can now go ahead and create a location trigger. But before you can do this, you need to ask the user’s permission to receive push notifications.

Notification Authorization

For notifications and configuring a UNLocationNotificationTrigger, you’ll need to use the UserNotifications API.

Open LocationManager.swift and beneath the import for CoreLocation, add:

import UserNotifications

Next, add the following to the top of the LocationManager class with the other properties:

let notificationCenter = UNUserNotificationCenter.current()

Here, you create a reference to the system’s shared notification center. This is the brain for all things notifications in iOS.

Still in LocationManager.swift, add the following method to the bottom of the class:

// 1
func requestNotificationAuthorization() {
  // 2
  let options: UNAuthorizationOptions = [.sound, .alert]
  // 3
  notificationCenter
    .requestAuthorization(options: options) { result, _ in
      // 4
      print("Notification Auth Request result: \(result)")
    }
}

The code above does the following:

  1. Creates a method to request notification authorization.
  2. Defines the notification’s capabilities and requests the ability to play sounds and display alerts.
  3. Requests authorization from the user to show local notifications.
  4. The completion block prints the results of the authorization request to the debugger.

You want to show this to users when they place an order.

Navigate to DetailView.swift and locate requestNotification(). At the bottom of the method, add:

locationManager.requestNotificationAuthorization()

Now, the user will get prompted for notification authorization after placing an order.

Build and run, and then place an order.

The notification authorization step happens each time you place an order. The first time you run a notification authorization in a particular app, you should see an alert requesting permission to send notifications, if they are not enabled by default:

Notification Permissions Prompt

Tap Allow. You’ll see the following printed to the debugger:

Notification Auth Request result: true

Your app is ready to receive notifications. Next, you’ll configure and handle a local notification.

Using UNLocationNotificationTrigger to Notify the User

With permission to receive a push notification added, it’s time to configure one.

Open LocationManager.swift and add the following method to the bottom of the LocationManager class:

// 1
private func registerNotification() {
  // 2
  let notificationContent = UNMutableNotificationContent()
  notificationContent.title = "Welcome to Swifty TakeOut"
  notificationContent.body = "Your order will be ready shortly."
  notificationContent.sound = .default

  // 3
  let trigger = UNLocationNotificationTrigger(
    region: storeRegion,
    repeats: false)

  // 4
  let request = UNNotificationRequest(
    identifier: UUID().uuidString,
    content: notificationContent,
    trigger: trigger)

  // 5
  notificationCenter
    .add(request) { error in
      if error != nil {
        print("Error: \(String(describing: error))")
      }
    }
}

This method does the following:

  1. Creates a method to register a notification.
  2. Creates content for a notification. UNMutableNotificationContent is the object used for representing the content of a notification. Here, you’re setting the title, body and sound properties of this object.
  3. Creates a location trigger condition that causes the notification to appear. This gets triggered when you enter the storeRegion.
  4. Configures a UNNotificationRequest object to request a notification with the notificationContent and trigger. A unique identifier is set in this request. This is useful if you need to cancel a notification.
  5. Adds the request to schedule the notification.

With this added, you need to update requestNotificationAuthorization() to register a notification, if allowed. This requires two modifications. First, change the .requestAuthorization(options: options) { result, _ in line to what’s shown below:

.requestAuthorization(options: options) { [weak self] result, _ in

You’re adding [weak self] to the capture list for the completion block. That allows you to access the properties of the class from inside the completion block.

Next, after print("Notification Auth Request result: \(result)"), add:

if result {
  self?.registerNotification()
}

This code tests the authorization result to see if the user has given permission to receive notifications. If so, register the region trigger notification.

Now, users should get notified when they enter the region.