1. 程式人生 > >Implement Push Notifications in iOS with Swift

Implement Push Notifications in iOS with Swift

Implement Push Notifications in iOS with Swift

https://medium.com/@franciscoigor/implement-push-notifications-in-ios-with-swift-ca6d962ae214

In this post we implement Push Notifications in iOS with Swift. Actually, this process is easier than before, with only a small set of steps:

  1. Activate Push notifications in your iOS project
  2. Request permissions for User notifications
  3. Register in Apple Push Notifications service
  4. Sending Test notifications
  5. Handling Notifications in your app

Get an Apple Developer Account

First of all, you need an Apple Developer Account

 to access the Apple Push Notifications service. However, you can see this post this post about how to Publish an iOS application in the App Store if you need to create an account for the first time.

Activate Push notifications in your iOS project

  1. Open the application project properties
     (the root icon in your project)
  2. In General, define an unique “Application Bundle” name. For example, me.developer.ios.notifications.
  3. In the Capabilities section, activate “Push Notifications”. As a result, your App ID will be automatically registered in the App Store.

 

You can check your app registration in the Apple Developer web site, in the section Identifiers -> App IDs:

Request permission for User notifications

To request permission for User notifications in your application, you need to add some extra methods to your ViewController. You can add it as a separated extension, to keep it reusable for other projects:

 

import UIKit
import UserNotifications

extension UIViewController {
    
    func getNotificationSettings() {
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            //print("User Notification settings: \(settings)")
            guard settings.authorizationStatus == .authorized else { return }
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
    
    func requestNotificationAuthorization(){
        // Request for permissions
        UNUserNotificationCenter.current()
            .requestAuthorization(
            options: [.alert, .sound, .badge]) {
                [weak self] granted, error in
                //print("Notification granted: \(granted)")
                guard granted else { return }
                self?.getNotificationSettings()
        }
    }
     
}

The first method getNotificationSettings() is to ensure your User notification settings could be restored if the user revokes the authorization, and the the user could activate the permission again. Also, after checking the permission, it will call registerForRemoteNotifications() to enable remote notifications as well.

The second method requestNotificationAuthorization is to request the user permission to send notifications. The options (UNAuthorizationOptions) part is to select the types of notifications to show. A confirmation dialog will appear to let the user activate or disable the user notifications for your application.

Request authorization in your application

Then, in your application view initialization (For example, in viewDidLoad()), you can call the request for authorization. Now, this method is part of the View Controller.

import UIKit

class ViewController: UIViewController {

   override func viewDidLoad() {
        super.viewDidLoad()
        requestNotificationAuthorization()
    }


}

Getting an access token for testing

You can add an extra code in your AppDelegate to get a special Device Tokento test push notifications manually in your phone. Again, this could be done adding an extension to your AppDelegate:

import UIKit

extension AppDelegate {
    
    func application(
        _ application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
        ) {
        let tokenParts = deviceToken.map 
            { data in String(format: "%02.2hhx", data) }
        let token = tokenParts.joined()
        print("My Device Token: \(token)")
    }
    
    func application(
        _ application: UIApplication,
        didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Error registering notifications: \(error)")
    }
}

This code will show you in the console a Device Token to test push notifications. Take note of this code when you run the application for the first time. Also, the second method will show you whatever error you get when registering Push Notifications. This could be helpful if you are getting some issues or errors when notifications are not working, like this:

Error registering notifications: Error Domain=NSCocoaErrorDomain Code=3010 "remote notifications are not supported in the simulator" UserInfo={NSLocalizedDescription=remote notifications are not supported in the simulator}

In this case, you cannot test remote push notifications in a Simulator. You need to run your application in a real phone device.

Running for the first time

When you run this application for the first time, you will view the User Notification permission request at the start of the execution:

After that, you will also get some console output about this process:

Notification granted: true
User Notification settings: <UNNotificationSettings: 0x282834380; authorizationStatus: Authorized, notificationCenterSetting: Enabled, soundSetting: Enabled, badgeSetting: Enabled, lockScreenSetting: Enabled, carPlaySetting: NotSupported, criticalAlertSetting: NotSupported, alertSetting: Enabled, alertStyle: Banner, providesAppNotificationSettings: No>
My Device Token: 930976dfb191c5085b72aa347ad91c561a6fcdaab639c173a015f0745ee11401

Register in Apple Push Notifications service

Create an Authentication Key

First of all, you need to go to the Apple Developer account portal, and create an Authentication Key for your application:

  1. Under Keys -> All, you can create a new Key pressing the [+] button.
  2. Input the name for your Application Key. For example, PushNotificationsKey.
  3. Save and confirm your key
  4. Download the backup in your computer

 

Test Push Notifications

You can test remote push notifications with a very useful utility called “Push Notifications”. You can download the release for MacOs and run for testing Push Notifications in your device.

  1. Download PushNotifications
  2. Unzip and run the application.
  3. Be sure the first time you run the application, do it with right click on the icon, and choose Open from the menu
  4. If you run the application normally, you probably get a warning: the application is not signed, and cannot be opened.
  5. In Authentication, select Token.
  6. Click Select P8 button and select the .p8 file downloaded previously.
  7. Enter your Key ID and Team ID in the relevant fields.
  8. Key ID is the ID of the Authentication key created in the previous step, you can get the code from https://developer.apple.com/account/ios/authkey/
  9. Team ID is the ID of your Apple Developer Account, you can get the code from https://developer.apple.com/account/#/membership/
  10. Enter the App Bundle ID and your device token.
  11. App bundle ID is the ID of the application you entered in the first part (example: me.developer.ios.notifications)
  12. Your Device Token is printed in the console when you run the application in your phone from the Xcode project.
  13. Create the request body like the following example:
  • { “aps”: { “alert”: “New Notification”, “sound”: “default”, “link_url”: “https://developerhowto.com" } }
  1. Press the pink button Send, and you will receive a notification in your phone using the information provided in the previous request body.

 

Push Notification Format

A Push notification can contain seven different attributes:

  • alert: Its the main message. It could be a plain String or a localizable message (multiple languages) using a list of keys/values (Dictionary).
  • badge: A number that will display in the corner of the app icon (0 = disabled).
  • sound: A name of a custom notification short sound’s located in the app.
  • thread-id: Used in group notifications.
  • category: This defines the category of the notification, It can be used to personalize different actions when receiving the notification.
  • content-available: It makes the push notification silent (1=silent).
  • mutable-content: Allows to modify the notification before displaying it (1=mutable).

Handling Push Notifications in your app

Handling Notifications during initialization

You can manage the Notifications received during the application loading. To do that, you need to add extra code to your AppDelegate, inside the application() method with didFinishLaunchingWithOptions.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        // Check remote notification
        let notificationOption = launchOptions?[.remoteNotification]
        if let notification = notificationOption as? [String: AnyObject],
            let aps = notification["aps"] as? [String: AnyObject] {
            // Process remote notification in the view
            let main = window?.rootViewController as! ViewController
            main.initialNotification = aps
        }
        
        return true
    }

This code takes the notification data and passes this data to the main ViewController, which has an attribute initialNotification to receive an initial notification. Inside the ViewController, now we can process a remote notification with this updated code:

import UIKit

class ViewController: UIViewController {
    
    var initialNotification : [String : AnyObject]?

    override func viewDidLoad() {
        super.viewDidLoad()
        requestNotificationAuthorization()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        if let app = initialNotification {
            let alert = UIAlertController(title: app["category"] as? String, message: app["alert"] as? String, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }


}

When the applications appears on the screen. This code will show an alertwith the category and message (alert) of the last notification received.

To test this code you need to start your application with a different Scheme. In other words, this code will execute only when the application starts. So, you need to change the Run Scheme to “Wait “:

  1. In Xcode, Go to Product -> Scheme -> Edit Scheme…
  2. Change the Run Scheme to “Wait for executable to be launched”
  3. Save your preferences and Run again
  4. This time, the application will only compile and wait for you to activate
  5. Launch a new Notification using the PushNotifications app with this code:
  • { “aps”: { “alert”: “4 New Notifications!”, “sound”: “default”, “link_url”: “https://developerhowto.com/", “category” : “Notify”, “badge” : 4 } }
  1. Click on the notification on your phone and the application will launch showing the alert.

Handling Notification during execution

The first part will only work for an application previously stopped. However, if the application is running, it needs extra code, in order to capture the notification.

Change the ViewController code to match both situations:

override func viewDidAppear(_ animated: Bool) {
        if let aps = initialNotification {
            processNotification(aps: aps)
        }
    }
    
    func processNotification(aps: [String : AnyObject]){
        let alert = UIAlertController(title: aps["category"] as? String, message: aps["alert"] as? String, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil))
        self.present(alert, animated: true, completion: nil)
    }

Adding a new method to the AppDelegate extension for didReceiveRemoteNotification to capture Notifications while running:

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
        }
        let main = window?.rootViewController as! ViewController
        main.processNotification(aps: aps)
    }

Full Project Code

You can download, clone or fork the code samples and the project itself from the GitHub project https://github.com/fraigo/ios-push-notifications.

Enjoy your Notifications!

NoteThis post was originally posted inhttps://developerhowto.com/2018/12/07/implement-push-notifications-in-ios-with-swift/