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?
Registering With APNs
Now that you have permissions, you’ll register for remote notifications!
In getNotificationSettings()
, add the following beneath the print
inside the closure:
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
Here, you verify the authorizationStatus
is .authorized
: The user has granted notification permissions. If so, you call UIApplication.shared.registerForRemoteNotifications()
to kick off registration with the Apple Push Notification service. You need to call this on the main thread, or you’ll receive a runtime warning.
Add the following to the end of AppDelegate
:
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
}
This method is called by iOS whenever a call to registerForRemoteNotifications()
succeeds. The code may look cryptic, but it’s simply taking a received deviceToken
and converting it to a string. The device token is the fruit of this process. It’s provided by APNs and uniquely identifies this app on this particular device.
When sending a push notification, the server uses tokens as “addresses” to deliver to the correct devices. In your app, you would now send this token to your server to save and use later on for sending notifications.
Now add the following:
func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
print("Failed to register: \(error)")
}
This method is called by iOS if registerForRemoteNotifications()
fails. You’re just printing the error for now.
That’s it! Build and run. Because you are on a simulator, you’ll see a Failed to register
error. You can ignore that for now. Later, when you run on a real device, you should receive a token in the console output. Here’s an example:
Sending a Simulated Push Notification
Use a text editor to create a file called first.apn, which you’ll pass to Xcode’s simctl utility. Paste in the following JSON text and save the file.
{
"aps": {
"alert": "Breaking News!",
"sound": "default",
"link_url": "https://raywenderlich.com"
}
}
The structure of this JSON will be explained in the next section. Patience, grasshopper.
Build and run the app again on the simulator, then background the app or lock the device. The app is not yet able to process push notifications while in the foreground.
To use simctl, you’ll need to know the device identifier for the simulator that you are running the app in. If there is only one device running in the simulator, you can use booted instead of an identifier. To get the identifier, in Xcode, select Windows ▸ Devices and Simulators, then select the Simulators tab at the top and select the simulator you’re using from the list on the left. Use your mouse to copy the identifier. You might need to widen the dialog box to see it fully.
Open the Terminal app and change to the directory where you saved first.apn. Then type in the following command using either booted or the device identifier from Xcode in place of device_identifier: xcrun simctl push device_identifier bundle_identifier first.apn
. Replace device_identifier
with the device identifier you copied from Xcode and replace bundle_identifier
with the app’s bundle identifier — the one you used when you first set up the project. Here’s an example:
Run the command and you’ll see the push notification appear on the simulator!
Tap on the notification to launch the app.
Isn’t that cool? :]
Looking at a Basic Push Notification
Before you move on to handling push notifications, take a look at the body of the notification you’ve sent:
{
"aps": {
"alert": "Breaking News!",
"sound": "default",
"link_url": "https://raywenderlich.com"
}
}
The payload is a JSON dictionary that contains at least one item, aps, which is also a dictionary. In this example, aps
contains the fields alert
, sound
, and link_url
. When the device receives this push notification, it shows an alert view with the text “Breaking News!” and plays the standard sound effect.
link_url
is actually a custom field. You can add custom fields to the payload like this, and they will get delivered to your application. Because you aren’t handling it inside the app yet, this key/value pair currently does nothing.
link_url
should be at a peer level to the aps
dictionary entry rather than inside of it. It still works if you place it inside, but we always suggest adhering to Apple’s documentation and will correct this in our next update to this tutorial.There are eight built-in keys you can add to the aps
dictionary (see the official Payload Key Reference for more information):
- alert: This can be a string, as in the previous example, or a dictionary. As a dictionary, it can localize the text or change other aspects of the notification.
- badge: This is a number that will display in the corner of the app icon. You can remove the badge by setting this to 0.
- sound: Name of a custom notification sound’s file located in the app. These must be shorter than 30 seconds.
- thread-id: Use this key to group notifications.
- category: This defines the category of the notification, which is used to show custom actions on the notification. You’ll explore this shortly.
-
content-available: By setting this key to
1
, the push notification becomes silent. You’ll learn about this in the Silent Push Notifications section below. -
mutable-content: By setting this key to
1
, your app can modify the notification before displaying it. - target-content-id: This is the identifier of the window brought forward.
Outside of these, you can add as much custom data as you want, as long as the payload does not exceed 4,096 bytes.
Once you’ve had enough fun trying out these options and sending push notifications to your simulator, move on to the next section!