推播通知 UserNotifications with iOS 10 up

來使用推播傳遞你的心聲吧!

在iOS 10 之後,原本推播使用的LocalNotification已經被取代了。
今天來練習的就是目前最新的推播中心。

首先,要記得引入新的Modal: UserNotifications

import UserNotifications

接著,要建立一個常數來當作整個推播的控制中心

let center = UNUserNotificationCenter.current()

存取權限

既然是推播通知,那請一定要記得取得使用著的權限,才不會讓使用者收不到你辛辛苦苦寫好的通知。

取得使用者權限的程式碼,我是直接寫在 AppDelegate.swift裡的

application:didFinishLaunchingWithOptions:

讓使用者在開啟程式後就能選擇是否授權。

在通知的類別: Types的方面,總共有四種,分別是:alert, sound, badge, carPlay。

在貼上程式碼之前,要先來說一下在 UNUserNotificationCenter控制中心裡面的setting,必須要用 function

getNotificationSettings(CompletionHandler:)

才能進行讀取。
(而不是像以前一樣設定一個常數為notificationSetting)

在 AppDelegate.swift中,使用到的是 settings.authorizationStatus,在這之中,一共有三種狀況,分別是 .notDetermined, .authorized, .denied。

而現在的目的是取得使用者的授權,也就是在使用者第一次執行App時,還在 .notDetermined的狀態

self.center.requestAuthorization(options: options) {
(granted, error) in
if !granted {
print("Something went wrong")
}
}

使用 requestAuthorization(options: completionHandler:) 來取得使用者的授權。

建立一個推播通知 Notification Request

一個通知由三個要素組成:identifier、content以及 trigger。

Notification Identifier

identifier就是你這通知的唯一身份證,如果多個通知用一樣的身份證,新的通知會取代舊的。

let identifier = "MyUniqueIdentifier"

Notification Content

當你建立一個通知時,需要建立一個 UNMutableNotificationContent並且設定其中的參數:

title: 通知的標題,為字串 String。向使用者告知為何需要這則通知。
subtitle: 副標題,為字串 String,為optional。
body: 通知的內容,為字串 String,一樣是optional
badge: 標記的數字,可以像某些日期App設定顯示的數字。
sound: 通知顯示的鈴聲,使用UNNotificationSound.default()取得預設鈴聲。
launchImageName: 這個參數我還沒實驗,這裡可以設定一個特定的圖片名稱或是Storyboard裡的特定View Controller,在使用者點選該通知時,就會顯示你指定的圖片/頁面。
userInfo: 為Dictionary[String: Any]形式的資料型態,可顯示在通知中。
attachments: 為一個內容為 UNNotificationAttachment的陣列 Array,可以儲存影片、圖片或是音源檔。

簡單的一個例子:

let content = UNMutableNotificationContent() 
content.title = "It's a notification"
content.body = "Hello, what's up?"
content.sound = UNNotificationSound.default()

Notification Trigger

最後一個要素是觸發器,格式可以使用Time、Canlendar或是 Location。
同時可以設定是否重複。

● TimeInterval: 設定觸發器為一個timeInterval,讓通知在多少秒數後觸發:

let trigger = UITimeIntervalNotificationTrigger(timeInterval:60, repeats: false)

上面的例子中,秒數間隔為60秒。要注意的是秒數至少要超過60,才可以設定為repeats。

● Calendar: 設定觸發器為calendar的形式,有特定的日期和時間,同時可以更容易設定repeats:像是每日重複或是每週重複。

let date = Date(timeIntervalSinceNow: 36000)
let triggerDate = Canlendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: false)

每日重複(每日同一時間、分,秒):

let triggerDaily = Calendar.current.dateComponents([.hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)

每週重複,除了設定時間外還要再多設定一個weekday:

let triggerWeekly = Calendar.current.dateComponents([.weekday, .hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerWeekly, repeats: true)

● Location: 設定觸發器當使用者靠近或離開一個特定地點 CoreLocation CLRegion。

let triggerLocation = UNLocationNotificationTrigger(triggerWithRegion: region, repeats: false)

Scheduling a Notification Request

現在identifier、content,trigger都設定好後,就可以來建立通知了!

let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
if let error = error {
//Make some error handling here
}
})

這樣就完成設定推播通知啦!

Custom Actions

設定特定的動作,讓使用者在接收到通知時,藉由這些動作觸發更多功能。

蘋果官方的文件:

Action要正常運作還需要設定控制中心的Delegate:

UNUserNotificationCenterDelegate

最後來要介紹UNUserNotificationCenterDelegate,在這之中一共有兩個 optional methods:

userNotificationCenter(_:willPresent:withCompletionHandler:)

第一個方法是在你的推播在使用其他的 App跳出時,會用什麼樣的方式 (UNNotificationPresentationOptions) 顯示。
我在這邊設定的是 [.alert, .sound, .badge],也就是包含通知本身,聲音以及標記。
你也可以設定 .none來忽略推播。

userNotificationCenter(_:didReceive:withCompletionHandler:)

第二個方法是來設定當使用者選擇了特定的 UNNotificationAction時,做出的反應。
在上面範例中,我是拿鬧鐘的貪睡功能 Snooze來練習,

在按了 Snooze Action後,即會再多產生一個一樣的推播通知,在5秒後產生。

在實作時,為了在建立通知時確認使用者是否有授權,再次叫出了 settings.authorizationStatus,如果是 .denied的情況,就會有個 Alert請使用者去開啟權限!

Pending & Delivered Notification

最後再提一下,在UNUserNotificationCenter中,還有幾個方法可以來變更、查看,刪除在佇列或已傳送的通知。

getPendingNotificationRequests(completionHandler:)
removePendingNotificationRequests(withIdentifiers:)
removeAllPendingNotificationRequests()

印出Pending的Request:

getDeliveredNotificationRequests(completionHandler:)
removeDeliveredNotificationRequests(withIdentifiers:)
removeAllDeliveredNotificationRequests()

--

--