本地通知
需要加引用.加庫
swift寫法:
import UserNotifications
oc寫法:
#import <UserNotifications/UserNotifications.h>
一. 注冊通知
通知中心只有一個(gè),用類方法UNUserNotificationCenter.current()獲取
requestAuthorization后,彈出對話框讓用戶選擇,是否同意通知權(quán)限.用戶選擇一次后,下次再也不會彈出了,會默認(rèn)認(rèn)定上次用戶的選擇結(jié)果.
granted參數(shù):
為true: 用戶同意,請求權(quán)限成功
為false: 用戶拒絕,請求通知權(quán)限失敗
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
// Enable or disable features based on authorization.
}
//最好能立刻指定代理 ,該代理的文檔說:delegate必須在app結(jié)束launch的時(shí)候設(shè)置,可以在appdelegate的
//application(_:willFinishLaunchingWithOptions:)或者 application(_:didFinishLaunchingWithOptions:)中設(shè)置
center.delegate = self
- 有人會說:用戶也可以后期在設(shè)置中修改通知設(shè)置,確實(shí).
所以用這個(gè)方法實(shí)時(shí)獲取用戶的設(shè)置:
center.getNotificationSettings { (UNNotificationSettings) in
print("settsing is :\(UNNotificationSettings)")
}
二. 發(fā)送通知
創(chuàng)建一個(gè)[UNNotificationRequest,把它add到通知中心中
trigger決定通知的發(fā)送情況,是重復(fù)發(fā)送,還是一次.有好幾種:
- UNCalendarNotificationTrigger : 日歷鬧鐘,和NSDateComponents結(jié)合,可以做到在每天指定的時(shí)刻發(fā)送通知,官網(wǎng)例子:
let date = DateComponents()date.hour = 8date.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
- UNTimeIntervalNotificationTrigger: 定時(shí)鬧鐘
- UNLocationNotificationTrigger:地點(diǎn)鬧鐘,和CLLocationCoordinate2D結(jié)合,可以做到進(jìn)入了某個(gè)固定區(qū)域時(shí)發(fā)送通知,官網(wǎng)例子:
let center = CLLocationCoordinate2D(latitude: 37.335400, longitude: -122.009201)
let region = CLCircularRegion(center: center, radius: 2000.0, identifier: "Headquarters")
region.notifyOnEntry = true
region.notifyOnExit = false
let trigger = UNLocationNotificationTrigger(region: region, repeats: false)
OK!不扯遠(yuǎn)了,開始干!
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationStringForKey("Hello!", arguments: nil)
content.body = NSString.localizedUserNotificationStringForKey("Hello_message_body", arguments: nil)
content.sound = UNNotificationSound.default()
// Deliver the notification in five seconds.
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let request = UNNotificationRequest(identifier: "FiveSecond", content: content, trigger: trigger)
// Schedule the notification.
let center = UNUserNotificationCenter.current()
center.add(request)
三. 代理方法
通知到達(dá)后,兩個(gè)代理方法:
1. willPresent...
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Swift.Void){
completionHandler([UNNotificationPresentationOptions.alert, UNNotificationPresentationOptions.badge, UNNotificationPresentationOptions.sound])
//completionHandler([])
}
注意:
這個(gè)方法是app在前臺時(shí)進(jìn)入的.app如果在后臺不會進(jìn)入
請務(wù)必在最后一句寫上completionHandler,同時(shí)指定你需要的通知到達(dá)時(shí)的形式.另外,如果想通知達(dá)到時(shí)不做任何事情,swift寫:completionHandler([]) oc寫:completionHandler(UNNotificationPresentationOptionNone);
completionHandler后的任何代碼都不執(zhí)行,所以讓completionHandler放在你的邏輯代碼之后
app在前臺時(shí),通知形式可以指定,那么app在后臺呢?文檔告訴我們,屆時(shí)的通知形式由我們注冊通知中心時(shí)申請的形式,以及用戶在設(shè)置里面的選擇共同決定,當(dāng)然,在選擇上,用戶設(shè)置的形式 是高于 我們申請的形式 的優(yōu)先級的.
2. 點(diǎn)擊通知才會進(jìn)入的方法didReceive
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Swift.Void){
completionHandler()
}
**注意: **
- UNNotificationResponse的屬性actionIdentifier:
用戶點(diǎn)擊的category的哪個(gè)action的identifier.如果用戶是直接點(diǎn)擊的通知,沒點(diǎn)action,這個(gè)值是default,請自行打印了解 - 無論app是否被殺死,無論是從橫幅還是通知欄點(diǎn)擊進(jìn)入app,該方法都會被調(diào)用一次,我測試過的.
四.其他要點(diǎn)
1. 注冊通知寫在何處?
官網(wǎng)推薦寫在application:didFinishLaunchingWithOptions:
總之不能寫在scheduling一個(gè)本地/遠(yuǎn)程通知之后.
2. 刪除過期通知
getDeliveredNotificationsWithCompletionHandler:
獲取通知欄上的消息removeDeliveredNotificationsWithIdentifiers: 刪除通知欄上的消息
如果哪個(gè)通知過期了,是你不想給用戶看到的,可以刪除通知欄上的消息.當(dāng)然,如果用戶的通知欄上本就沒有這消息,可能剛到的時(shí)候就被用戶點(diǎn)掉了,那么獲取的通知欄消息數(shù)為0.可以在getDeliveredNotificationsWithCompletionHandler的回調(diào)塊中去刪除通知欄上的消息
3. Action和category
一個(gè)通知可以注冊多個(gè)category. 發(fā)送通知時(shí),UNMutableNotificationContent選擇一個(gè)category進(jìn)行綁定
每個(gè)category可以有很多action,官網(wǎng)說最多4個(gè),顯示最多兩個(gè),我實(shí)驗(yàn)發(fā)現(xiàn)5個(gè)都行,而且全部顯示-_-
通知達(dá)到時(shí),要用重力按壓,就會出現(xiàn)action
代碼十分簡單:
let generalCategory = UNNotificationCategory(identifier: "GENERAL",
actions: [],intentIdentifiers: [],options: .customDismissAction)
// Create the custom actions for the TIMER_EXPIRED category.
let snoozeAction = UNNotificationAction(identifier: "SNOOZE_ACTION",title: "Snooze",options: UNNotificationActionOptions(rawValue: 0))
let stopAction = UNNotificationAction(identifier:"STOP_ACTION",title: "Stop",options: .foreground)
let expiredCategory =UNNotificationCategory(identifier: "TIMER_EXPIRED",actions: [snoozeAction, stopAction],intentIdentifiers: [],options: UNNotificationCategoryOptions(rawValue: 0))
// Register the notification categories.
let center = UNUserNotificationCenter.current()
center.setNotificationCategories([generalCategory, expiredCategory])
在發(fā)送通知消息時(shí),把UNMutableNotificationContent的categoryIdentifier賦值為category的identifier,就可以了
let content = UNMutableNotificationContent()
content.title = "coffee"
content.body = "Time for another cup of coffee!"
content.sound = UNNotificationSound.default()
//**就是這里,要和上面的category的identifier一致**
content.categoryIdentifier = "GENERAL";
let trigger = UNTimeIntervalNotificationTrigger(timeInterval:3, repeats:false)
let request = UNNotificationRequest(identifier:"TIMER_EXPIRED", content:content,trigger:trigger)
UNUserNotificationCenter.current().add(request) { error in
print("注冊成功!")
}
效果:
點(diǎn)擊之后的處理
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
if response.notification.request.content.categoryIdentifier == "TIMER_EXPIRED" {
// Handle the actions for the expired timer.
if response.actionIdentifier == "SNOOZE_ACTION" {
// Invalidate the old timer and create a new one. . .
}
else if response.actionIdentifier == "STOP_ACTION" {
// Invalidate the timer. . .
}
}
// Else handle actions for other notification types. . .
}
4. 官網(wǎng)還提供了類似"鬧鐘"的例子,每天七點(diǎn)鬧醒你!
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: "Wake up!", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: "Rise and shine! It's morning time!",
arguments: nil)
// Configure the trigger for a 7am wakeup.
var dateInfo = DateComponents()
dateInfo.hour = 7
dateInfo.minute = 0
let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: false)
// Create the request object.
let request = UNNotificationRequest(identifier: "MorningAlarm", content: content, trigger: trigger)
5. 改變通知的聲音
通知的聲音是可以改變的.UNNotificationSound.default()只是系統(tǒng)鈴聲而已.
聲音文件可以放在bundle里面,也可以在線下載,放在APP沙盒的Library/Sounds里.
content.sound = UNNotificationSound(named: "MySound.aiff")