iOS Push Notifications: Part 6— Local Pushes

Dmitrijs Beloborodovs
Citadele Bank Developers
3 min readMar 26, 2024

Speaking about notifications we can’t skip locals.

Photo by Tim Mossholder on Unsplash

The quote from documentation

Use local notifications to get the user’s attention. You can display an alert, play a sound, or badge your app’s icon. For example, a background app could ask the system to display an alert when your app finishes a particular task. Always use local notifications to convey important information that the user wants.

The system handles delivery of notifications based on a time or location that you specify. If the delivery of the notification occurs when your app isn’t running or in the background, the system interacts with the user for you. If your app is in the foreground, the system delivers the notification to your app for handling.

Local pushes are quite similar to remote push notifications. You need to ask user’s permission to receive them. There are three “triggers” when notification should be fired:

  • UNCalendarNotificationTrigger defines date/time for notification. Repeating also available. The following example will trigger notification every day (repeats: true) on 10:30.
var date = DateComponents()
date.hour = 10
date.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
  • UNTimeIntervalNotificationTrigger describe interval for repeated notifications. The following code will trigger in 1 min (60 sec multiply once). With repeats: true it will be fired every minute.
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: (60 * 1),
repeats: false
)
  • UNLocationNotificationTrigger is about location. You app must have when-in-use permission. The following example triggers notification when in radius of 100m around specified location.
let center = CLLocationCoordinate2D(
latitude: 56.95342222403206,
longitude: 24.100736051500316
)
let region = CLCircularRegion(
center: center,
radius: 100.0,
identifier: "Headquarters"
)
region.notifyOnEntry = true
region.notifyOnExit = false
let trigger = UNLocationNotificationTrigger(
region: region,
repeats: false
)

To create notification payload a special object used UNMutableNotificationContent.

let content = UNMutableNotificationContent()
content.title = "Incoming payment"
content.body = "Check you balance"
content.userInfo = ["category": "PAY_IN"]

With that you are ready to schedule notification

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

// Schedule the request with the system.
let notificationCenter = UNUserNotificationCenter.current()
do {
try await notificationCenter.add(request)
} catch {
print("\(#function)\n\(error)")
}

Local notification treated by system same way as remote: with userNotificationCenter(_:willPresent:) if app is in foreground, and userNotificationCenter(_:didReceive:) when app is in background. The only difference is payload. The user info object still available at notification → request → content → userInfo. But for, i.e. title refer to notification → request → content → title, it won’t be inside userInfo JSON.

You can also retrieve list of all scheduled notifications

let notificationCenter = UNUserNotificationCenter.current()
let requests = await notificationCenter.pendingNotificationRequests()

And delete those you don’t need anymore.

let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removePendingNotificationRequests(
withIdentifiers: ["<notification_id>"]
)

Feel free to play with source code.

References

--

--