There are two types of notifications in iOS: local notification and remote notification.

Local notifications

Using the step

  1. The importUserNotificationsThe module.
  2. Apply for permission.
  3. Creating notification contentUNMutableNotificationContent, can be set:

(1) Title: indicates the title of notification. (2) Subtitle: notification subtitle. (3) The body of the notification. A. sound B. sound C. sound D. sound (5) Badge: Horn. (6) userInfo: Additional information. (7) categoryIdentifier: Category unique identifier. (8) Attachments, which can be pictures, audio and video, displayed in the drop-down notification. 3. Specify the local notify the trigger condition, there are three kinds of trigger mode: (1) UNTimeIntervalNotificationTrigger: after a period of time. (2) UNCalendarNotificationTrigger: specify the date/time trigger. (3) UNLocationNotificationTrigger: according to the position trigger. 4. Create an UNNotificationRequest based on the notification content and triggering conditions. 5. Add UNNotificationRequest to UNUserNotificationCenter.

case

  • Request authorization (asynchronous operation).
import UserNotifications

func application(_ application: UIApplication.didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Request notification permission
    UNUserNotificationCenter.current()
        .requestAuthorization(options: [.alert, .sound, .badge]) { // Banners, sounds, markers
            (accepted, error) in
            if !accepted {
                print("User does not allow notifications")}}return true
}
Copy the code
  • Send notifications.
import CoreLocation
import UIKit
import UserNotifications

class ViewController: UIViewController {
    override func viewDidLoad(a) {
        super.viewDidLoad()
    }

    // Trigger after a period of time
    @IBAction func timeInterval(_ sender: Any) {
        // Set the content to be pushed
        let content = UNMutableNotificationContent()
        content.title = "Hello"
        content.subtitle = "Hi"
        content.body = "This is an interval based test notification."
        content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "feiji.wav"))
        content.badge = 1
        content.userInfo = ["username": "YungFan"."career": "Teacher"]
        content.categoryIdentifier = "testUserNotifications1"
        setupAttachment(content: content)

        // Set the notification trigger
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
        
        // Set the request identifier
        let requestIdentifier = "com.abc.testUserNotifications2"
        // Set a notification request
        let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
        // Add the notification request to the sending center
        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)}// Specify a date and time trigger
    @IBAction func dateInterval(_ sender: Any) {
        // Set the content to be pushed
        let content = UNMutableNotificationContent()
        content.title = "Hello"
        content.body = "This is a date-based test notification."
        
        / / time
        var components = DateComponents()
        components.year = 2021
        components.month = 5
        components.day = 20
        // Every Monday at 8 a.m
        // var components = DateComponents()
        // Weekday = 2 // Monday
        Hour = 8 // 8 a.m
        // components. Minute = 30 // 30 minutes
        // Set the notification trigger
        let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
        
        // Set the request identifier
        let requestIdentifier = "com.abc.testUserNotifications3"
        // Set a notification request
        let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
        // Add the notification request to the sending center
        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)}// Triggers by location
    @IBAction func locationInterval(_ sender: Any) {
        // Set the content to be pushed
        let content = UNMutableNotificationContent()
        content.title = "Hello"
        content.body = "This is a location-based test notification."
        
        / / position
        let coordinate = CLLocationCoordinate2D(latitude: 31.29065118, longitude: 118.3623587)
        let region = CLCircularRegion(center: coordinate, radius: 500, identifier: "center")
        region.notifyOnEntry = true // Triggers when entering this range
        region.notifyOnExit = false // Leaving the range does not trigger
        // Set the trigger
        let trigger = UNLocationNotificationTrigger(region: region, repeats: true)
        // Set the request identifier
        let requestIdentifier = "com.abc.testUserNotifications"
        
        // Set a notification request
        let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
        // Add the notification request to the sending center
        UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)}}extension ViewController {
    func setupAttachment(content: UNMutableNotificationContent) {
        let imageURL = Bundle.main.url(forResource: "img", withExtension: ".png")!
        do {
            let imageAttachment = try UNNotificationAttachment(identifier: "iamgeAttachment", url: imageURL, options: nil)
            content.attachments = [imageAttachment]
        } catch {
            print(error.localizedDescription)
        }
    }
}
Copy the code

Remote Notification (Notification Push)

Remote Notification, also known as Apple Push Notification Services (APNs), refers to the Notification that is pushed by the remote server to the client when the network is connected. When connected to the Internet, all devices have a persistent connection to An Apple server, so they can receive remote notifications pushed by the server regardless of whether the app is open or closed.

Realize the principle of

  1. When the App is opened, it first sends the UDID and BundleID to APNs for registration and returns deviceToken (steps 1,2,3 in the figure).
  2. After an App obtains the deviceToken, the App sends the relevant information and deviceToken to the application server through API, and the server records the information. (Step 4 in the figure)
  3. When a notification is to be pushed, the application server finds the stored deviceToken based on App information and sends the notification and deviceToken to APNs. (Step 5 in the figure)
  4. APNs uses deviceToken to find the specified App of the specified device and push the notification out. (Step 6 in the figure)

Implementation steps

Certificate of way

  1. Add App IDs to the Identifiers on your developer site and open Push Notifications in Capabilities.
  2. Create an APNs certificate for Apple Push Notification Service SSL (Sandbox & Production) in Certificates and associate it with the App IDs in step 1. Then download the certificate to a local PC and install it. After the installation, you can export the P12 certificate.
  3. Select Capability in the project, then enable Push Notifications, and then select Remote Notifications in Background Modes.
  4. Apply for permission.
  5. throughUIApplication.shared.registerForRemoteNotifications()Request deviceToken from APNs.
  6. throughfunc application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)Obtain deviceToken. If the deviceToken is obtained normally, the registration is successful and the remote notification can be pushed. Finally, the remote notification needs to be sent to the application server. Note:
    • DeviceToken does not change after App restarts.
    • After the App is uninstalled and reinstalled, deviceToken changes.
  7. Notify tests.

Token way

  1. Find the Team ID in the Membership of the developer’s website and record it.
  2. Register a Key in Keys of Certificates, Identifiers & Profiles and check Apple Push Notifications Service (APNs), Finally, the generated Key ID is recorded and the AuthKey of P8 is downloaded locally (only once).
  3. Select Capability in the project, then enable Push Notifications, and then select Remote Notifications in Background Modes.
  4. Apply for permission.
  5. throughUIApplication.shared.registerForRemoteNotifications()Request deviceToken from APNs.
  6. throughfunc application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)Obtain deviceToken. If the deviceToken is obtained normally, the registration is successful and the remote notification can be pushed. Finally, the remote notification needs to be sent to the application server.
  7. Notify tests.

Token Authentication is a new push Authentication mode launched by APNs. It has the following advantages:

(1) All apps under the same developer account, whether the test version or the official version, can be sent using the same Key instead of generating certificates for each App. (2) The generation of Key process is relatively simple, do not need the cumbersome certificate operation process, and it no longer has an expiration time, do not need to be like a certificate to periodically regenerate.

AppDelegate

import UserNotifications

class AppDelegate: UIResponder.UIApplicationDelegate {
    func application(_ application: UIApplication.didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Request notification permission
        UNUserNotificationCenter.current()
            .requestAuthorization(options: [.alert, .sound, .badge]) {
                accepted, _ in
                if !accepted {
                    print("Users do not allow notifications.")}}// Request deviceToken from APNs
        UIApplication.shared.registerForRemoteNotifications()

        return true
    }

    // deviceToken request success callback
    func application(_ application: UIApplication.didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        var deviceTokenString = String(a)let bytes = [UInt8](deviceToken)
        for item in bytes {
            deviceTokenString + = String(format: "%02x", item & 0x000000FF)}// Print the obtained token string
        print(deviceTokenString)
        
        // Send the token to the server over the network
    }
    
    // deviceToken request failed callback
    func application(_ application: UIApplication.didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print(error.localizedDescription)
    }
}
Copy the code

Note: Remote notifications do not support emulators (direct access to deviceToken request failure callbacks) and must be tested on real machines.

test

Real machine test

  1. Install the App on the real machine.
  2. Test through software (such as APNs) or a third party, but the relevant content needs to be set up.

(1) Certificate mode: P12 certificate + Bundle Identifier + deviceToken. (2) Token: P8 AuthKey + Team ID + Key ID + Bundle Identifier + deviceToken.

Emulator tests – Using JSON files

  • JSON file.
{
  "aps": {"alert": {"title":"Test"."subtitle":"Remote Push"."body":"This is a message from far away."
    },
    "sound":"default"."badge":1}}Copy the code
  • Command.
xcrun simctl push booted developer.yf.TestUIKit /Users/yangfan/Desktop/playload.json
Copy the code

Simulator tests – using APNS files

Another way is to drag the APNs file directly into the iOS emulator. Prepare a file with the.apns suffix, similar to the JSON file above, but with a Simulator Target Bundle that describes the App’s Bundle Identifier.

  • APNs file.
{
  "Simulator Target Bundle": "developer.yf.TestUIKit"."aps": {"alert": {"title":"Test"."subtitle":"Remote Push"."body":"This is a message from far away."
    },
    "sound":"default"."badge":1}}Copy the code

The front desk to deal with

By default, the App can only receive notifications in the background, but not in the foreground. If the foreground also needs reminders, you can perform the following operations.

  • Create UNUserNotificationCenterDelegate.
class NotificationHandler: NSObject.UNUserNotificationCenterDelegate {
    // Display notifications in front
    func userNotificationCenter(_ center: UNUserNotificationCenter.willPresent notification: UNNotification.withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) - >Void) {
        // The front desk notification does not set badge generally
        completionHandler([.list, .banner, .sound])

        // If you don't want to display a notification, you can use []
        // completionHandler([])}}Copy the code
  • Set up the proxy.
class AppDelegate: UIResponder.UIApplicationDelegate {
    // Custom notification callback class to implement notification proxy
    let notificationHandler = NotificationHandler(a)func application(_ application: UIApplication.didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Set the proxy
        UNUserNotificationCenter.current().delegate = notificationHandler
        
        return true}}Copy the code

Angle of the set

  • Whether it is local or remote notification, foreground notification generally does not set the logo reminder, so only need to process the logo for background notification.
  • You do not need to manually set the notification icon. It is automatically set according to the notification.
// Add the marker manually
UIApplication.shared.applicationIconBadgeNumber = 10

// Clean up the corner marker
UIApplication.shared.applicationIconBadgeNumber = 0
Copy the code