Acting on responses
Acting on responses êŽë š
Thereâs a lot more you can do with notifications, but chances are the thing you most want to do is act on the userâs response â to show one or more options alongside your alert, then respond to the userâs choice.
We already set the categoryIdentifier
property for our notification, which is a text string that identifies a type of alert. We can now use that same text string to create buttons for the user to choose from, and iOS will show them when any notifications of that type are shown.
This is done using two new classes: UNNotificationAction
creates an individual button for the user to tap, and UNNotificationCategory
groups multiple buttons together under a single identifier.
For this technique project weâre going to create one button, âShow me moreâŠâ, that will cause the app to launch when tapped. Weâre also going to set the delegate
property of the user notification center to be self
, meaning that any alert-based messages that get sent will be routed to our view controller to be handled.
Creating a UNNotificationAction
requires three parameters:
- An identifier, which is a unique text string that gets sent to you when the button is tapped.
- A title, which is what userâs see in the interface.
- Options, which describe any special options that relate to the action. You can choose from
.authenticationRequired
,.destructive
, and.foreground
.
Once you have as many actions as you want, you group them together into a single UNNotificationCategory
and give it the same identifier you used with a notification.
Thatâs it! Add this method to ViewController
now:
func registerCategories() {
let center = UNUserNotificationCenter.current()
center.delegate = self
let show = UNNotificationAction(identifier: "show", title: "Tell me moreâŠ", options: .foreground)
let category = UNNotificationCategory(identifier: "alarm", actions: [show], intentIdentifiers: [])
center.setNotificationCategories([category])
}
You might have noticed the empty intentIdentifiers
parameter in the category initializer - this is used to connect your notifications to intents, if you have created any.
Youâll get an error because you assigned self
to be the delegate of the user notification center. To fix it, make the ViewController
class conform to UNUserNotificationCenterDelegate
like this:
class ViewController: UIViewController, UNUserNotificationCenterDelegate {
You can call registerCategories()
wherever you want, but in this project the safest place is probably right at the beginning of the scheduleLocal()
method.
Now that we have registered the âalarmâ category with a single button, the last thing to do is implement the didReceive
method for the notification center. This is triggered on our view controller because weâre the centerâs delegate, so itâs down to us to decide how to handle the notification.
We attached some customer data to the userInfo
property of the notification content, and this is where it gets handed back â itâs your chance to link the notification to whatever app content it relates to.
When the user acts on a notification you can read its actionIdentifier
property to see what they did. We have a single button with the âshowâ identifier, but thereâs also UNNotificationDefaultActionIdentifier
that gets sent when the user swiped on the notification to unlock their device and launch the app.
So: we can pull out our user info then decide what to do based on what the user chose. The method also accepts a completion handler closure that you should call once youâve finished doing whatever you need to do. This might be much later on, so itâs marked with the @escaping
keyword.
Hereâs the code â add this method to ViewController
now:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
// pull out the buried userInfo dictionary
let userInfo = response.notification.request.content.userInfo
if let customData = userInfo["customData"] as? String {
print("Custom data received: \(customData)")
switch response.actionIdentifier {
case UNNotificationDefaultActionIdentifier:
// the user swiped to unlock
print("Default identifier")
case "show":
// the user tapped our "show more infoâŠ" button
print("Show more informationâŠ")
default:
break
}
}
// you must call the completion handler when you're done
completionHandler()
}
Our project now creates notifications, attaches them to categories so you can create action buttons, then responds to whichever button was tapped by the user â weâre done!