Push Notifications Tutorial: Getting Started
Push notifications allow developers to reach users, even when users aren’t actively using an app! In this tutorial, you’ll learn how to configure your app to receive push notifications and to display them to your users or perform other tasks. By Chuck Krutsinger .
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
Push Notifications Tutorial: Getting Started
35 mins
- Getting Started
- Sending and Receiving Push Notifications
- Configuring the App
- Enabling the Push Notification Service
- Asking for User Notifications Permission
- Registering With APNs
- Sending a Simulated Push Notification
- Looking at a Basic Push Notification
- Handling Push Notifications
- Understanding What Happens When You Receive a Push Notification
- Working With Actionable Notifications
- Handling Notification Actions
- Sending to a Real Device
- Troubleshooting Common Issues
- Using Silent Push Notifications
- Where to Go From Here?
Handling Push Notifications
In this section, you’ll learn how to perform actions when your app receives notifications and when users tap them.
Understanding What Happens When You Receive a Push Notification
When your app receives a push notification, iOS calls a method in UIApplicationDelegate
.
You’ll need to handle a notification differently depending on what state your app is in when the notification is received:
- If your app wasn’t running and the user launches it by tapping the push notification, iOS passes the notification to your app in the
launchOptions
ofapplication(_:didFinishLaunchingWithOptions:)
. - If your app was running either in the foreground or the background, the system notifies your app by calling
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
. When the user opens the app by tapping the push notification, iOS may call this method again, so you can update the UI and display relevant information.
In the first case, WenderCast will create the news item and open directly to the News tab. In AppDelegate.swift, add the following code to the end of application(_:didFinishLaunchingWithOptions:)
, just before the return statement:
// Check if launched from notification
let notificationOption = launchOptions?[.remoteNotification]
// 1
if
let notification = notificationOption as? [String: AnyObject],
let aps = notification["aps"] as? [String: AnyObject] {
// 2
NewsItem.makeNewsItem(aps)
// 3
(window?.rootViewController as? UITabBarController)?.selectedIndex = 1
}
This is what you’re doing:
- Check whether the value for
UIApplication.LaunchOptionsKey.remoteNotification
exists inlaunchOptions
. If it does, then your app was launched from a notification. This will contain the push notification payload you sent. - Since the
aps
dictionary exists, create aNewsItem
with it. - Change the selected tab of the tab controller to the News section.
To test this, you need to edit the scheme of WenderCast. First, build and run to install the latest code on the simulator. Then, click the WenderCast scheme and select Edit Scheme…:
Select Run from the sidebar, then in the Info tab select Wait for executable to be launched:
This option will make the debugger wait for the app to be launched for the first time after installing to attach to it.
Build and run. Once it’s done installing, send out more breaking news using xcrun simctl
as before. Tap the notification, and the app will open to news:
To handle the situation where your app is running when a push notification is received, add the following to AppDelegate
:
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler:
@escaping (UIBackgroundFetchResult) -> Void
) {
guard let aps = userInfo["aps"] as? [String: AnyObject] else {
completionHandler(.failed)
return
}
NewsItem.makeNewsItem(aps)
}
This tries to extract the aps from the supplied userInfo
object and, if successful, creates a new NewsItem
from it.
Since iOS calls this method when the app is running, you need to change the scheme back to launching the app automatically to test it. In the Scheme editor, under Launch, select Automatically.
Build and run. Keep the app running in the foreground and on the News tab. Send another news push notification and watch as it appears in the feed:
That’s it! Your app now can magically receive breaking news as it happens. :]
Working With Actionable Notifications
Actionable notifications let you add custom buttons to the notification itself. You might have noticed this on email notifications or Tweets that let you “reply” or “favorite” on the spot.
Your app can define actionable notifications when you register for notifications by using categories. Each category of notification can have a few preset custom actions.
Once registered, your server can set the category of a push notification. The corresponding actions will be available to the user when received.
For WenderCast, you’ll define a News category with a custom action named View. This action will allow users to view the news article in the app if they choose to.
In registerForPushNotifications()
, insert the following just below the guard and above the call to getNotificationSettings()
:
// 1
let viewAction = UNNotificationAction(
identifier: Identifiers.viewAction,
title: "View",
options: [.foreground])
// 2
let newsCategory = UNNotificationCategory(
identifier: Identifiers.newsCategory,
actions: [viewAction],
intentIdentifiers: [],
options: [])
// 3
UNUserNotificationCenter.current().setNotificationCategories([newsCategory])
Going through this, step-by-step:
- Create a new notification action, with the title View on the button, that opens the app in the foreground when triggered. The action has a distinct identifier, which iOS uses to differentiate between other actions on the same notification.
- Define the news category, which will contain the view action. This also has a distinct identifier that your payload will need to contain to specify that the push notification belongs to this category.
- Register the new actionable notification by calling
setNotificationCategories
.
Build and run the app to register the new notification settings.
Background the app and then send the following payload via the xcrun simctl
utility:
{
"aps": {
"alert": "Breaking News!",
"sound": "default",
"link_url": "https://raywenderlich.com",
"category": "NEWS_CATEGORY"
}
}
When the notification appears, pull down on it to reveal the View action:
Nice! Tapping View will launch WenderCast, but it doesn’t do anything exciting just yet. To get it to display the news item, you need to do some more event handling in the delegate.
Handling Notification Actions
Whenever a notification action gets triggered, UNUserNotificationCenter
informs its delegate. Back in AppDelegate.swift, add the following class extension to the bottom of the file:
// MARK: - UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
// 1
let userInfo = response.notification.request.content.userInfo
// 2
if
let aps = userInfo["aps"] as? [String: AnyObject],
let newsItem = NewsItem.makeNewsItem(aps) {
(window?.rootViewController as? UITabBarController)?.selectedIndex = 1
// 3
if response.actionIdentifier == Identifiers.viewAction,
let url = URL(string: newsItem.link) {
let safari = SFSafariViewController(url: url)
window?.rootViewController?
.present(safari, animated: true, completion: nil)
}
}
// 4
completionHandler()
}
}
This is the callback you get when the app opens because of a custom action. It might look like there’s a lot going on, but there’s not much new here:
- Get the
userInfo
dictionary. - Create a
NewsItem
from theaps
dictionary and navigate to the News tab. - Check the
actionIdentifier
. If it is the “View” action and the link is a valid URL, it displays the link in anSFSafariViewController
. - Call the completion handler the system passes to you.
There is one last bit: You have to set the delegate on UNUserNotificationCenter
. Add this line to the top of application(_:didFinishLaunchingWithOptions:)
:
UNUserNotificationCenter.current().delegate = self
Build and run. Close the app again, then send another news notification with the following payload:
{
"aps": {
"alert": "New Posts!",
"sound": "default",
"link_url": "https://raywenderlich.com",
"category": "NEWS_CATEGORY"
}
}
Pull down the notification and tap the View action, and you’ll see WenderCast present a Safari View controller right after it launches:
Congratulations, you’ve implemented an actionable notification! Send a few more and try opening the notification in different ways to see how it behaves.