0

Giới thiệu về UserNotifications Framework

Introduction

Với iOS 10, tvOS 10 và watchOS 3, Apple đang giới thiệu một framework mới được gọi là UserNotifications. Bộ API mới này cung cấp một cách thống nhất, theo hướng đối tượng để làm việc với các thông báo cục bộ và từ xa trên các nền tảng này. Điều này là đặc biệt hữu ích khi, so với các API hiện có, các thông báo cục bộ và từ xa bây giờ được xử lý rất giống nhau, và truy cập vào nội dung thông báo được thực hiện không chỉ thông qua các dictionary. Trong bài viết này mình sẽ đi sâu vào framework này và cách để bạn có thể dễ dàng tận dụng lợi thế của framework này vào ứng dụng của bạn.

Registering for Notifications

Trước khi sử dụng bất kỳ API UserNotifications nào, bạn cần phải thêm dòng import sau:

import UserNotifications

Tiếp theo, để đăng ký ứng dụng của bạn cho các notification, bạn sẽ cần phải thêm đoạn code sau vào AppDelegate của bạn trong method application(:didFinishLaunchingWithOptions:):

let center = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .badge, .sound]
center.requestAuthorization(options: options) { (granted, error) in
    if granted {
        application.registerForRemoteNotifications()
    }
}

Đầu tiên ta get một tham chiếu đến current UNUserNotificationCenter . Tiếp theo ta đăng ký để sử dụng remote notification. Lưu ý rằng bạn có thể có bất kỳ sự kết hợp các tùy chọn ở đây, ví dụ như chỉ alert hoặc cùng với badge và sound. Sử dụng cả hai đối tượng này, sau đó chúng ta yêu cầu ủy quyền cho ứng dụng bạn để hiển thị notification bằng cách gọi requestAuthorization(options:completionHandler:). Complete handle có 2 tham số truyền vào cho nó.

  • Một giá trị Bool biểu thị có hoặc không được cấp quyền bởi người dùng.
  • Một đối tượng tùy chọn Error sẽ chứa thông tin nếu vì một số lý do, hệ thống đã không thể để yêu cầu được cấp phép thông báo cho ứng dụng của bạn. Bạn sẽ thấy rằng trong đoạn code trên, nếu ủy quyền được cấp bởi người dùng, chúng tôi sẽ đăng ký remote notification. Nếu bạn muốn implement remote notification, dòng code này là bắt buộc. Bạn cũng sẽ phải làm một số thiết lập thêm cho dự án của bạn, như được mô tả chi tiết sau đây: Xin lưu ý rằng việc đăng ký remote notification sẽ gọi phương thức callback UIApplication tương tự như trong phiên bản iOS trước đây. Khi thành công, application(:didRegisterForRemoteNotificationsWithDeviceToken:), sẽ được gọi và application(:didFailToRegisterForRemoteNotificationsWithError:) sẽ được gọi khi thất bại.

Scheduling Notifications

Trong phần này chúng ta sẽ tập trung hoàn toàn vào schedule local notification sử dụng framework UserNotification. Một local notification trước khi được schedule sẽ được đại diện bởi một instance của UNNotificationRequest class. Đối tượng của loại hình này bao gồm các thành phần sau:

  • Identifier: một String duy nhất cho phép bạn phân biệt các thông báo với nhau.
  • Content: một đối tượng UNNotificationContent chứa tất cả các thông tin cần thiết để hiển thị các thông báo của bạn, bao gồm cả tiêu đề, phụ đề và biểu tượng ứng dụng.
  • Trigger: một đối tượng UNNotificationTrigger được sử dụng bởi hệ thống để xác định khi nào thông báo của bạn nên được "gửi" đến ứng dụng của bạn. Để bắt đầu, chúng ta sẽ xem xét các kiểu trigger khác nhau mà bạn có thể thiết lập cho các local notification. UNNotificationTrigger class là một lớp trừu tượng, có nghĩa là bạn sẽ không bao giờ trực tiếp tạo ra đối tượng của nó, thay vào đó bạn sử dụng các lớp con có sẵn. Hiện tại, framework UserNotifications cung cấp ba lớp con cho bạn:
  • UNTimeIntervalNotificationTrigger, cho phép một notification được gửi đi một khoảng thời gian sau khi lên lịch nó.
  • UNCalendarNotificationTrigger, cho phép một notification sẽ được gửi tại một thời điểm cụ thể, bất kể nó đã được lên lịch khi nào.
  • UNLocationNotificationTrigger, cho phép một notification được gửi khi người dùng vào hoặc rời khỏi một khu vực địa lý đã định. Code sau đây cho bạn thấy cách làm thế nào bạn có thể kích hoạt các loại trigger trên:
let timeTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 60.0 * 60.0, repeats: false)
 
var date = DateComponents()
date.hour = 22
let calendarTrigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
 
let center = CLLocationCoordinate2D(latitude: 40.0, longitude: 120.0)
let region = CLCircularRegion(center: center, radius: 500.0, identifier: "Location")
region.notifyOnEntry = true;
region.notifyOnExit = false;
let locationTrigger = UNLocationNotificationTrigger(region: region, repeats: false)

Với code ở trên, các điều kiện kích hoạt sau đây đã được tạo ra:

  • TimeTrigger sẽ được kích hoạt một giờ sau khi notification được schedule. Tham số timeInterval được truyền vào UNTimeIntervalNotificationTrigger được xác định trong vài giây.
  • calendarTrigger sẽ liên tục được kích hoạt hàng ngày lúc 10:00. Thời điểm chính xác của việc kích hoạt dễ dàng có thể được thay đổi bằng cách sửa đổi các thược tính khác của đối tượng DateComponents mà bạn truyền vào UNCalendarNotificationTrigger.
  • locationTrigger sẽ được kích hoạt khi người dùng đến cách 500m tọa độ cho trước, trong trường hợp này 40°N 120°E. Như bạn có thể thấy từ code, kiểu kích hoạt này có thể được sử dụng cho bất kỳ kích thước toạ độ hoặc khu vực nào để có thể kích hoạt các notification sau khi cả vào hoặc ra khỏi khu vực đó. Tiếp theo, chúng ta cần tạo nội dung cho notification. Điều này được thực hiện bằng cách tạo một instance của UNMutableNotificationContent class. Class này phải được sử dụng như lớp UNNotificationContent thông thường có quyền đọc đối với các thuộc tính nội dung notification khác nhau. Code sau đây cho thấy cách tạo ra nội dung của một notification cơ bản:
let content = UNMutableNotificationContent()
content.title = "Notification Title"
content.subtitle = "Notification Subtitle"
content.body = "Some notification body information to be displayed."
content.badge = 1
content.sound = UNNotificationSound.default()

Cuối cùng, chúng ta chỉ cần tạo ra đối tượng UNNotificationRequest và lên schedule cho nó

let request = UNNotificationRequest(identifier: "LocalNotification", content: content, trigger: timeTrigger)
UNUserNotificationCenter.current().add(request) { error in
    if let error = error {
        // Thất bại
    } else {
        // Thành công
    }
}

Bắt đầu với code này, chúng ta tạo ra đối tượng yêu cầu bằng cách truyền qua một identifier, đối tượng nội dung và kích hoạt vào trong phương thức khởi tạo. Sau đó chúng ta gọi phương thức add(_:completionHandler:) trên đối tượng current UNUserNotificationCenter.

Receiving Notifications

Khi sử dụng UserNotifications Framework, việc xử lý các notification đến được xử lý bởi một đối tượng mà bạn chỉ định conform với giao thức UNUserNotificationCenterDelegate. Đối tượng này có thể là bất cứ điều gì bạn muốn và không cần phải là delegate của ứng dụng như trong các phiên bản iOS trước đây. Tuy nhiên, một điều quan trọng cần lưu ý là bạn cần phải set delegate trước khi ứng dụng của bạn được khởi chạy đầy đủ. Đối với ứng dụng iOS, điều đó có nghĩa là bạn phải gán delegate của bạn bên trong hai method application(:willFinishLaunchingWithOptions:) hoặc application(:didFinishLaunchingWithOptions:) trong app delegate. Set delegate cho UserNotification được thực hiện rất dễ dàng với code sau:

UNUserNotificationCenter.current().delegate = delegateObject

Bây giờ sau khi đã set delegate, khi nhận được notification của ứng dụng, chỉ có 2 method ta cần quan tâm. Cả 2 method được truyền qua đối tượng UNNotification, đại diện cho notification nhận được. Đối tượng này chứa thuộc tính date, giúp bạn biết được chính xác khi nào notification được phát đi, và thuộc tính request là một đối tượng của lớp UNNotificationRequest đã đề cập trước đó. Từ đối tượng request đó, ta có thể xem truy cập nội dung của notification cũng như kích hoạt notification đó(nếu cần). Trigger object này sẽ là một đối tượng của một lớp con UNNotificationTrigger đã đề cập trước đó, hoặc trong trường hợp push notification là một đối tượng của lớp UNPushNotificationTrigger. Method đầu tiên được định nghĩa bởi các giao thức UNUserNotificationCenterDelegate là method userNotificationCenter(:willPresent:withCompletionHandler:). Method này chỉ được gọi là khi ứng dụng của bạn đang chạy ở foreground và nhận được một notification. Từ đây, ta có thể truy cập nội dung notification và hiển thị giao diện tùy biến riêng của mình bên trong ứng dụng nếu cần thiết. Ngoài ra, bạn có thể cho hệ thống hiển thị notification với nhiều tùy chọn. Các tùy chọn có sẵn là:

  • Alert để hiển thị giao diện hệ thống tạo ra cho thông báo
  • Sound âm thanh kết hợp với thông báo
  • Badge để chỉnh sửa badge number của ứng dụng Sau đây là ví dụ về việc implement method userNotificationCenter(:willPresent:withCompletionHandler:) :
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    let content = notification.request.content
    // Xử lý nội dung notification
     
    completionHandler([.alert, .sound]) // Hiển thị notification với alert và sound
}

Một method khác được define bởi giao thức UNUserNotificationCenterDelegate là method userNotificationCenter(:didReceive:withCompletionHandler:). Method này được gọi khi người dùng tương tác với notification theo bất kỳ hình thức nào, bao gồm cả dissmiss hoặc open notification đó. Thay vì một đối tượng UNNotification, method này có một đối tượng UNNotificationResponse được truyền vào nó như là một tham số. Đối tượng này chứa đối tượng UNNotification đại diện cho thông báo được gửi. Nó cũng bao gồm một thuộc tính actionIdentifier để xác định cách người dùng tương tác với notification. Trong trường hợp notification bị dismiss hoặc open, framework UserNotifications cung cấp các action constant để bạn có thể so sánh. Sau đây là ví dụ của việc implement method userNotificationCenter(:didReceive:withCompletionHandler:):

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let actionIdentifier = response.actionIdentifier
     
    switch actionIdentifier {
    case UNNotificationDismissActionIdentifier: // Notification was dismissed by user
        // Do something
        completionHandler()
    case UNNotificationDefaultActionIdentifier: // App was opened from notification
        // Do something
        completionHandler()
    default:
        completionHandler()
    }
}

Xin lưu ý rằng đối với cả hai method delegate, điều cần thiết là bạn gọi completion handle ngay khi bạn xử lý xong thông báo. Một khi bạn thực hiện, hệ thống sau đó biết bạn đang thực hiện xong với notifiaction đó và có thể thực hiện bất kỳ quá trình cần thiết, chẳng hạn như đặt notification trong Notification Centre của người dùng. Managing Notifications Thỉnh thoảng người dùng ứng dụng của bạn nhận được nhiều notification trong khi app của bạn không chạy. Bạn có thể trực tiếp mở app mà không cần phải thông qua notification. Trong trường hợp này, cả 2 method của giao thức UNUserNotificationCenterDelegate đều không được gọi. Khi làm việc với local notification, đôi khi bạn muốn xóa scheduled notification trước khi hiển thị cho người dùng. Do đó UserNotifications framework cung cấp các method sau đây trên đối tượng UNUserNotificationCenter để làm việc với các local notifcation đang chờ và đã được gửi mà chưa được xử lý:

  • getPendingNotificationRequests(completionHandler:) cung cấp cho bạn một mảng của các đối tượng UNNotificationRequest trong completion handle. Mảng này sẽ chứa tất cả các local notification đã được scheduled nhưng chưa được kích hoạt
  • removePendingNotificationRequests(withIdentifiers:) loại bỏ tất cả scheduled local notifiaction với các định danh chứa trong mảng String bạn truyền vào như là một tham số.
  • removeAllPendingNotificationRequests loại bỏ tất cả scheduled local notifiaction trong ứng dụng của bạn.
  • getDeliveredNotifications(completionHandler:) cung cấp cho bạn một mảng của các đối tượng UNNotification trong completion handle. Mảng này sẽ chứa tất cả các notification được gửi cho ứng dụng của bạn mà vẫn có thể nhìn thấy trong Notification Centre của người dùng.
  • removeDeliveredNotifications(withIdentifiers:) loại bỏ tất cả các notification đã gởi với các định danh chứa trong mảng String mà bạn truyền vào từ Notification Centre của người dùng.
  • removeAllDeliveredNotifications loại bỏ tất cả các notification trong ứng dụng của bạn.

Custom Action Notifications

Đầu tiên, bạn phải define custom action và category mà ứng dụng của bạn bằng cách sử dụng các class UNNotificationActionUNNotificationCategory tương ứng. Đối với các action mà bạn muốn người dùng có thể input text, bạn có thể sử dụng lớp UNTextInputNotificationAction, là một lớp con của UNNotificationAction. Sau khi hành động và loại của bạn được xác định, sau đó bạn chỉ cần gọi phương thức setNotificationCategories(😃 trên current UNUserNotificationCenter. Code sau đây cho thấy bạn có thể dễ dàng đăng ký action trả lời và xoá notification loại message:

let replyAction = UNTextInputNotificationAction(identifier: "com.usernotificationstutorial.reply", title: "Reply", options: [], textInputButtonTitle: "Send", textInputPlaceholder: "Type your message")
let deleteAction = UNNotificationAction(identifier: "com.usernotificationstutorial.delete", title: "Delete", options: [.authenticationRequired, .destructive])
let category = UNNotificationCategory(identifier: "com.usernotificationstutorial.message", actions: [replyAction, deleteAction], intentIdentifiers: [], options: [])
center.setNotificationCategories([category])

Tiếp theo, khi người dùng sử dụng một trong những custom action của bạn, phương thức tương tự userNotificationCenter(:didReceive:withCompletionHandler:) mà chúng ta đã khái quát trước đó được gọi. Trong trường hợp này, định danh hành động của đối tượng UNNotificationResponse được truyền vào sẽ giống như cái mà bạn đã định nghĩa cho custom action của bạn. Điều quan trọng cần lưu ý là, nếu người dùng tương tác với một hành động nhập văn bản, thì đối tượng phản ứng được truyền qua phương thức này sẽ là kiểu của UNTextInputNotificationResponse. Code sau đây cho thấy một ví dụ cài đặt phương thức này, bao gồm cả logic cho các hành động tạo ra trước đó:

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let actionIdentifier = response.actionIdentifier
    let content = response.notification.request.content
     
    switch actionIdentifier {
    case UNNotificationDismissActionIdentifier: // Notification bị dismissed bởi user
        // Do something
        completionHandler()
    case UNNotificationDefaultActionIdentifier: // App được opened từ notification
        // Do something
        completionHandler()
    case "com.usernotificationstutorial.reply":
        if let textResponse = response as? UNTextInputNotificationResponse {
            let reply = textResponse.userText
            // Send reply message
            completionHandler()
        }
    case "com.usernotificationstutorial.delete":
        // Delete message
        completionHandler()
    default:
        completionHandler()
    }
}

Ngoài ra, nếu bạn muốn tận dụng lợi thế của các custom action cholocal notification của bạn, thì bạn có thể chỉ cần đặt thuộc tính categoryIdentifier trên đối tượng UNMutableNotificationContent của bạn khi tạo notification. Hy vọng bài viết sẽ bổ ích đối với các bạn


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí