本地通知
需要加引用.加库
swift写法:
import UserNotifications
oc写法:
#import <UserNotifications/UserNotifications.h>
一. 注册通知
通知中心只有一个,用类方法UNUserNotificationCenter.current()获取
requestAuthorization后,弹出对话框让用户选择,是否同意通知权限.用户选择一次后,下次再也不会弹出了,会默认认定上次用户的选择结果.
granted参数:
为true: 用户同意,请求权限成功
为false: 用户拒绝,请求通知权限失败
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
// Enable or disable features based on authorization.
}
//最好能立刻指定代理 ,该代理的文档说:delegate必须在app结束launch的时候设置,可以在appdelegate的
//application(_:willFinishLaunchingWithOptions:)或者 application(_:didFinishLaunchingWithOptions:)中设置
center.delegate = self
- 有人会说:用户也可以后期在设置中修改通知设置,确实.
所以用这个方法实时获取用户的设置:
center.getNotificationSettings { (UNNotificationSettings) in
print("settsing is :\(UNNotificationSettings)")
}
二. 发送通知
创建一个[UNNotificationRequest,把它add到通知中心中
trigger决定通知的发送情况,是重复发送,还是一次.有好几种:
- UNCalendarNotificationTrigger : 日历闹钟,和NSDateComponents结合,可以做到在每天指定的时刻发送通知,官网例子:
let date = DateComponents()date.hour = 8date.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
- UNTimeIntervalNotificationTrigger: 定时闹钟
- UNLocationNotificationTrigger:地点闹钟,和CLLocationCoordinate2D结合,可以做到进入了某个固定区域时发送通知,官网例子:
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!不扯远了,开始干!
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)
三. 代理方法
通知到达后,两个代理方法:
1. willPresent...
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Swift.Void){
completionHandler([UNNotificationPresentationOptions.alert, UNNotificationPresentationOptions.badge, UNNotificationPresentationOptions.sound])
//completionHandler([])
}
注意:
这个方法是app在前台时进入的.app如果在后台不会进入
请务必在最后一句写上completionHandler,同时指定你需要的通知到达时的形式.另外,如果想通知达到时不做任何事情,swift写:completionHandler([]) oc写:completionHandler(UNNotificationPresentationOptionNone);
completionHandler后的任何代码都不执行,所以让completionHandler放在你的逻辑代码之后
app在前台时,通知形式可以指定,那么app在后台呢?文档告诉我们,届时的通知形式由我们注册通知中心时申请的形式,以及用户在设置里面的选择共同决定,当然,在选择上,用户设置的形式 是高于 我们申请的形式 的优先级的.
2. 点击通知才会进入的方法didReceive
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Swift.Void){
completionHandler()
}
**注意: **
- UNNotificationResponse的属性actionIdentifier:
用户点击的category的哪个action的identifier.如果用户是直接点击的通知,没点action,这个值是default,请自行打印了解 - 无论app是否被杀死,无论是从横幅还是通知栏点击进入app,该方法都会被调用一次,我测试过的.
四.其他要点
1. 注册通知写在何处?
官网推荐写在application:didFinishLaunchingWithOptions:
总之不能写在scheduling一个本地/远程通知之后.
2. 删除过期通知
getDeliveredNotificationsWithCompletionHandler:
获取通知栏上的消息removeDeliveredNotificationsWithIdentifiers: 删除通知栏上的消息
如果哪个通知过期了,是你不想给用户看到的,可以删除通知栏上的消息.当然,如果用户的通知栏上本就没有这消息,可能刚到的时候就被用户点掉了,那么获取的通知栏消息数为0.可以在getDeliveredNotificationsWithCompletionHandler的回调块中去删除通知栏上的消息
3. Action和category
一个通知可以注册多个category. 发送通知时,UNMutableNotificationContent选择一个category进行绑定
每个category可以有很多action,官网说最多4个,显示最多两个,我实验发现5个都行,而且全部显示-_-
通知达到时,要用重力按压,就会出现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])
在发送通知消息时,把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("注册成功!")
}
效果:
点击之后的处理
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. 官网还提供了类似"闹钟"的例子,每天七点闹醒你!
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()只是系统铃声而已.
声音文件可以放在bundle里面,也可以在线下载,放在APP沙盒的Library/Sounds里.
content.sound = UNNotificationSound(named: "MySound.aiff")