Uncategorized

[iOS] Hướng dẫn xử lý với local notification

Đăng ký notification

Trong applicationDidFinishLaunchingWithOptions ở AppDelegate.swift chúng ta thực hiện.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
configApplePush(application)
return true
}

Trong file AppDelegate.swift thêm hàm phía dưới

func configApplePush(_ application: UIApplication) {
        if #available(iOS 10.0, *) {
            UNUserNotificationCenter.current().delegate = self
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
        } else {
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        }
        
        application.registerForRemoteNotifications()
    }

Send Notification

Để send một Local notification chúng ta cần những thông số như sau.

1. Nội dung

let content = UNMutableNotificationContent()
            content.title = "viết nội dung bạn muốn vào đây"
            content.body = "viết nội dung bạn muốn vào đây"
            content.sound = UNNotificationSound.default

Trên đây là cấu trúc rất đơn giản của một push chỉ gồm title, body text và âm thanh mặc định. Và chúng ta có thể custom được khá nhiều thứ với việc push này như cài đặt âm thanh cho push, truyền thêm object cho push …., phần này sẽ nói rõ hơn ở nội dung phía dưới.

2. Một Trigger

let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)

Ví dụ ở trên là 5 giây sau khi bạn đặt hẹn phát thì sẽ có notification push đến.
Ngoài ra còn có 2 loại trigger nữa là
UNCalendarNotificationTrigger Trigger cho phép bạn hẹn ngày, thời gian để phát thông báo.
UNLocationNotificationTrigger Trigger địa điểm. Khi user đến một địa điểm nào đó thì sẽ có thông báo.

3. Một request

let request = UNNotificationRequest(identifier: "viết nội dung bạn muốn vào đây", content: content, trigger: trigger)

Cuối cùng là 1 request. Bao gồm content ở (1) và trigger ở (2) và một định danh (identifier). identifier có ý nghĩa khi mà bạn push một thông báo có cùng định danh thì thông báo trước đó sẽ bị ghi đè bởi thông báo mới.

4. Add request

let center = UNUserNotificationCenter.current()
center.add(request)

request ở đây chính là request đã tạo ở mục 3

5. Ví dụ

import UIKit
import UserNotifications
 
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let center = UNUserNotificationCenter.current()
        let content = UNMutableNotificationContent()
        content.title = "Title"
        content.body = "Body"
        content.sound = UNNotificationSound.default()

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
        let request = UNNotificationRequest(identifier: "TestIdentifier", content: content, trigger: trigger)
        center.add(request)
    }
}

Hiển thị, xử lý notification khi app ở foreground, background

Trong file AppDelegate.swift thêm đoạn code sau vào

@available(iOS 10.0, *)
extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .sound])
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        // viết code bạn muốn xử lý vào đây
        completionHandler()
    }
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert, .sound])
}

Function trên dùng để hiển thị notification khi app đang ở chế độ foreground

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        // viết code bạn muốn xử lý vào đây
        completionHandler()
    }

Function trên xử lý khi click vào notification.

Một số lưu ý về local notification

1. Custom notification

ở đây khi custom notification thì có 1 vài lưu ý về âm thanh của notification:

  • notification chỉ có thể nhận được những file âm thanh có định dạng là: .m4a, .alaw, .µlaw, .pcm. Nếu file âm thanh không phải là 1 trong 4 định dạng trên thì sẽ phát âm thanh mặc định của hệ thống. Nhưng nếu lúc custom mà thực hiện việc ghi đè file âm thanh không phải đúng định dạng thì sẽ không phát được âm thanh -> ko thực hiện việc ghi đè âm thanh khi file không đúng định dạng là tốt nhất.
  • notification quy định độ dài của 1 file âm thanh không được vượt quá 30s. Nếu vượt quá 30s thì sẽ phát âm thanh mặc định của hệ thống.

2. Chuyển màn hình khi tap vào notification

Để thực hiện việc chuyển màn hình thì sẽ lắng nghe và thực hiện trong file AppDelegate.swift

Trong function dưới

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        // viết code bạn muốn xử lý vào đây
        completionHandler()
    }

thêm vào đoạn mã

handlerPushData()

nó sẽ trông như thế này

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        handlerPushData()
        completionHandler()
    }

trong function handlerPushData() thực hiện việc chuyển màn hình như đoạn mã

func handlerPushData(_ itemName: String?, _ genre: String?) {
        changeScene("ViewController bạn muốn chuyển đến", fromPush: true)
    }
func changeScene(_ controller: UIViewController, fromPush: Bool = false) {

        if let currentController = UserProps.shared.currentMainVC, let navigation = currentController.navigationController {
//            currentController.dismiss(animated: false, completion: nil)
            navigation.pushViewController(controller, animated: false)
        } else if let navigation = self.window?.rootViewController as? UINavigationController {
            navigation.navigationBar.isHidden = true
            navigation.pushViewController(controller, animated: false)
        } else {
            let navigation = UINavigationController(rootViewController: controller)
            navigation.navigationBar.isHidden = true
            if fromPush {
                UIApplication.shared.keyWindow?.rootViewController = navigation
                return
            }
            window = UIWindow(frame: UIScreen.main.bounds)
            window?.rootViewController = navigation
            window?.makeKeyAndVisible()
//            navigation.pushViewController(controller, animated: false)
        }
    }

trong đoạn code này thì lưu ý với những màn hình là dùng present để show thì sẽ thực hiện việc chuyển màn hình trước rồi mới dismiss màn hình đó đi và tuỳ vào trường hợp bài toán cụ thể các bạn có thể taọ thêm các biến để điều hướng đến màn hình mình mong muốn. Trên đây chỉ là 1 đoạn code đơn giản cho việc điều hướng nếu như các bạn đang ở màn main.