These days, having a visually stunning mobile app isnโt good enough. For your mobile app to see success, it must be designed with user experience (UX) in mind. Push Notifications are a great means of interacting with consumers even when they are not using the application.
This guide will walk you through setting up your project for rich push notifications, you will learn some server-side requirements and we will peek into the infinite possibilities!
In order to get started with push notifications, you need to follow these steps:
Edit
button. Under Push Notifications section there are two options for certificates as shown here. Select the Create Certificate button to create your Certificate.Development Certificate - App built from Xcode will receive notifications.
Production Certificate -App installed from Apple Store or Test Flight will receive notifications.
.pem/.p8
file you can easy convert it1$ openssl pkcs12 -in CertName.p12 -out CertName.pem -nodes -clcerts
Simply as that in your AppDelegate file:
1import UIKit
2import UserNotifications
3
4@UIApplicationMain
5class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
6
7 var window: UIWindow?
8
9func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
10
11 UNUserNotificationCenter.current().delegate = self
12
13 if #available(iOS 10, *) {
14 UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]) { granted, error in }
15 } else {
16 application.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
17 }
18 application.registerForRemoteNotifications()
19 return true
20 }
21...
Add the didRegisterForRemoteNotificationsWithDeviceToken
function in your AppDelegate.swift file to get the deviceToken, which will receive notifications.
1...
2func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
3 let deviceTokenString = deviceToken.reduce("") { $0 + String(format: "%02X", $1) }
4 print("APNs device token: \(deviceTokenString)")
5}
6...
Awesome! Now it's time to make them super duper nice-looking. ๐
Your notifications interface should feel like natural extension of your containing app!
A very important step for sending media attachment is the mutable-content
key in the push payload from the server. So let's take a look at this example payload.
1{
2 "aps": {
3 "alert": "Hello!",
4 "sound": "default",
5 "mutable-content": 1,
6 "badge": 1
7 },
8 "data": {
9 "attachment-url": "https://example.com/attachment.jpg"
10 }
11}
From Xcode > File > New > Target..., select Notification Service Extension and activate suggested scheme. Notice that there are two autogenerated files now - NotificationService.swift
and Info.plist.
In the NotificationService.swift
file, we need to handle the media URL from the payload. For example, we can use FileManager:
1...
2override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
3 self.contentHandler = contentHandler
4 bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
5
6 func failEarly() {
7 contentHandler(request.content)
8 }
9
10 guard let content = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
11 return failEarly()
12 }
13
14 guard let apnsData = content.userInfo["data"] as? [String: Any] else {
15 return failEarly()
16 }
17
18 guard let attachmentURL = apnsData["attachment-url"] as? String else {
19 return failEarly()
20 }
21
22 guard let imageData = NSData(contentsOf:NSURL(string: attachmentURL)! as URL) else { return failEarly() }
23 guard let attachment = UNNotificationAttachment.create(imageFileIdentifier: "image.gif", data: imageData, options: nil) else { return failEarly() }
24
25 content.attachments = [attachment]
26 contentHandler(content.copy() as! UNNotificationContent)
27 }
28...
... and this UNNotificationAttachment
extension function to save the media to disk:
1extension UNNotificationAttachment {
2 static func create(imageFileIdentifier: String, data: NSData, options: [NSObject : AnyObject]?) -> UNNotificationAttachment? {
3
4 let fileManager = FileManager.default
5 let tmpSubFolderName = ProcessInfo.processInfo.globallyUniqueString
6 let fileURLPath = NSURL(fileURLWithPath: NSTemporaryDirectory())
7 let tmpSubFolderURL = fileURLPath.appendingPathComponent(tmpSubFolderName, isDirectory: true)
8
9 do {
10 try fileManager.createDirectory(at: tmpSubFolderURL!, withIntermediateDirectories: true, attributes: nil)
11 let fileURL = tmpSubFolderURL?.appendingPathComponent(imageFileIdentifier)
12 try data.write(to: fileURL!, options: [])
13 let imageAttachment = try UNNotificationAttachment.init(identifier: imageFileIdentifier, url: fileURL!, options: options)
14 return imageAttachment
15 } catch let error {
16 print("error \(error)")
17 }
18
19 return nil
20 }
21}
Voila!
Let's add some actions to our Rich Push Notifications. Modify the payload by adding the "category" key to notify that we want to display actions.
1{
2 "aps": {
3 "alert": "Hello!",
4 "sound": "default",
5 "mutable-content": 1,
6 "badge": 1,
7 "category": "myCategoryName"
8 },
9 "data": {
10 "attachment-url": "https://example.com/attachment.jpg"
11 }
12}
In the autogenerated Notification Service Info.plist
, add an UNNotificationExtensionCategory array with up to 4 action identifiers. These can be seen as "Item 0" and "Item 1" in the picture below:
Adjust the notification category in your didReceiveRequest
function in the NotificationService.swift
file:
1...
2let meowAction = UNNotificationAction(identifier: "meow", title: "Meow", options: [])
3let pizzaAction = UNNotificationAction(identifier: "pizza", title: "Pizza?", options: [])
4
5let category = UNNotificationCategory(identifier: "myCategoryName", actions: [meowAction, pizzaAction], intentIdentifiers: [], options: [])
6UNUserNotificationCenter.current().setNotificationCategories([category])
7...
Simple as that! ๐ Time for a preview:
Finally, add the logic for the notifications buttons in the AppDelegate.swift
file, using the identifiers that we specified in the Info.plist
file earlier. The method we call is didReceive response from the UNUserNotificationCenterDelegate
1...
2func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
3
4 if response.actionIdentifier == "meow" {
5 ...
6 }
7 if response.actionIdentifier == "pizza" {
8 ...
9 }
10 completionHandler()
11 }
12...
Warning! Don't forget to update the badge icon number when needed!
1application.applicationIconBadgeNumber = 0
Last, but not least, let's add a custom preview for notifications from Xcode > File > New > Target... select Notification Content and activate suggested scheme. Now we have NotificationViewController.swift
, MainInterface.storyboard
and Info.plist
files.
The sky is the limit
Let your imagination run wild as you use your newfound abilities to build richer and richer push notifications for IOS apps. or take a look at the sample project included below to continue practicing with some cool ideas!
If you found this guide informative, engaging, or just plain awesome. Thanks for reading!