
iOS10更新變動(dòng)最大的就是通知這部分了,新版通知變得更加統(tǒng)一,使用更加方便,設(shè)計(jì)更加自由。以前本地通知和遠(yuǎn)程推送是分開的,雖然這些到了iOS10都合在一起了,但是為了便于理解,我們還是把他倆分開來進(jìn)行學(xué)習(xí)。這節(jié)我們學(xué)習(xí)的是本地通知。
以下的用語,如無特別表述,通知就代表本地通知,推送就代表遠(yuǎn)程服務(wù)器的推送。
快速添加一個(gè)通知
我們先舉個(gè)完整的代碼例子,大家了解下這個(gè)流程,然后分步介紹這幾項(xiàng):
//第一步:注冊(cè)通知
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
//請(qǐng)求獲取通知權(quán)限(角標(biāo),聲音,彈框)
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
//獲取用戶是否同意開啟通知
NSLog(@"request authorization successed!");
}
}];
}
//第二步:新建通知內(nèi)容對(duì)象
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]
content.title = @"iOS10通知";
content.subtitle = @"新通知學(xué)習(xí)筆記";
content.body = @"新通知變化很大,之前本地通知和遠(yuǎn)程推送是兩個(gè)類,現(xiàn)在合成一個(gè)了。這是一條測(cè)試通知,";
content.badge = @1;
UNNotificationSound *sound = [UNNotificationSound soundNamed:@"caodi.m4a"];
content.sound = sound;
//第三步:通知觸發(fā)機(jī)制。(重復(fù)提醒,時(shí)間間隔要大于60s)
UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];
//第四步:創(chuàng)建UNNotificationRequest通知請(qǐng)求對(duì)象
NSString *requertIdentifier = @"RequestIdentifier";
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requertIdentifier content:content trigger:trigger1];
//第五步:將通知加到通知中心
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
NSLog(@"Error:%@",error);
}];
最終效果如下:

通知內(nèi)容UNMutableNotificationContent
通知內(nèi)容就是設(shè)定通知的一些展示信息,iOS10之后可以設(shè)置subtitle。
聲音的設(shè)置需要借助一個(gè)新類UNNotificationSound,通知文件要放到bundle里面。另外在實(shí)際的測(cè)試過程中發(fā)現(xiàn),添加通知的聲音有時(shí)候會(huì)無效。這應(yīng)該是iOS10存在的一個(gè)bug,刪除掉程序,再安裝運(yùn)行就好了。
觸發(fā)機(jī)制UNNotificationTrigger
Trigger是新加入的一個(gè)功能,通過此類可設(shè)置本地通知觸發(fā)條件。它一共有一下幾種類型:
1、UNPushNotificaitonTrigger
推送服務(wù)的Trigger,由系統(tǒng)創(chuàng)建
2、UNTimeIntervalNotificaitonTrigger
時(shí)間觸發(fā)器,可以設(shè)置多長(zhǎng)時(shí)間以后觸發(fā),是否重復(fù)。如果設(shè)置重復(fù),重復(fù)時(shí)長(zhǎng)要大于60s
3、UNCalendarNotificaitonTrigger
日期觸發(fā)器,可以設(shè)置某一日期觸發(fā)。例如,提醒我每天早上七點(diǎn)起床:
NSDateComponents *components = [[NSDateComponents alloc] init];
components.hour = 7;
components.minute = 0; // components 日期
UNCalendarNotificationTrigger *calendarTrigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];
4、UNLocationNotificaitonTrigger
位置觸發(fā)器,用于到某一范圍之后,觸發(fā)通知。通過CLRegion設(shè)定具體范圍。
通知請(qǐng)求UNNotificationRequest
通知請(qǐng)求的構(gòu)造
+ (instancetype)requestWithIdentifier:(NSString *)identifier content:(UNNotificationContent *)content trigger:(nullable UNNotificationTrigger *)trigger;
就是把上面三項(xiàng)連接起來。它有一個(gè)參數(shù)identifier,這相當(dāng)于通知的一個(gè)身份。iOS10通知支持更新,就是基于此identifier再發(fā)一條通知。
通知中心UNUserNotificationCenter
獲取通知[UNUserNotificationCenter currentNotificationCenter]然后通過addNotificaitonRequest:就完成了一個(gè)通知的添加。
擴(kuò)展通知的內(nèi)容
通知我們已經(jīng)添加上了,現(xiàn)在我們需要擴(kuò)展一下通知的內(nèi)容,給它加一些內(nèi)容。擴(kuò)展的內(nèi)容需要支持3D-touch的手機(jī)(6s以上),重壓之后全面顯示
添加附件
iOS10之前通知的樣式不能更改,在iOS10之后引入了UNNotificationationAttachment,可以在通知中添加圖片,音頻,視頻。蘋果對(duì)這些附件的大小和類型有一個(gè)限制:

如果我想在通知里加一個(gè)圖片,可以這樣處理:
NSString *imageFile = [[NSBundle mainBundle] pathForResource:@"sport" ofType:@"png"];
UNNotificationAttachment *imageAttachment = [UNNotificationAttachment attachmentWithIdentifier:@"iamgeAttachment" URL:[NSURL fileURLWithPath:imageFile] options:nil error:nil];
content.attachments = @[imageAttachment];//雖然是數(shù)組,但是添加多個(gè)只能顯示第一個(gè)
/* add request and notificaiton code ... */
效果如下:

重壓之后:

添加交互
//點(diǎn)擊可以顯示文本輸入框
UNTextInputNotificationAction *action1 = [UNTextInputNotificationAction actionWithIdentifier:@"replyAction" title:@"文字回復(fù)" options:UNNotificationActionOptionNone];
//點(diǎn)擊進(jìn)入應(yīng)用
UNNotificationAction *action2 = [UNNotificationAction actionWithIdentifier:@"enterAction" title:@"進(jìn)入應(yīng)用" options:UNNotificationActionOptionForeground];
//點(diǎn)擊取消,沒有任何操作
UNNotificationAction *action3 = [UNNotificationAction actionWithIdentifier:@"cancelAction" title:@"取消" options:UNNotificationActionOptionDestructive];
//通過UNNotificationCategory對(duì)象將這幾個(gè)action行為添加到通知里去
UNNotificationCategory *categroy = [UNNotificationCategory categoryWithIdentifier:@"Categroy" actions:@[action1,action2,action3] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];
//將categroy賦值到通知內(nèi)容上
content.categoryIdentifier = @"Categroy";
//設(shè)置通知代理,用于檢測(cè)點(diǎn)擊方法
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
/* add request and notificaiton code ... */
效果如下:


獲取通知交互內(nèi)容:
//識(shí)別通知交互處理的代理方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler{
NSString *categoryIdentifier = response.notification.request.content.categoryIdentifier;
if ([categoryIdentifier isEqualToString:@"Categroy"]) {
//識(shí)別需要被處理的拓展
if ([response.actionIdentifier isEqualToString:@"replyAction"]){
//識(shí)別用戶點(diǎn)擊的是哪個(gè) action
UNTextInputNotificationResponse *textResponse = (UNTextInputNotificationResponse*)response;
//獲取輸入內(nèi)容
NSString *userText = textResponse.userText;
//發(fā)送 userText 給需要接收的方法
NSLog(@"要發(fā)送的內(nèi)容是:%@",userText);
//[ClassName handleUserText: userText];
}else if([response.actionIdentifier isEqualToString:@"enterAction"]){
NSLog(@"點(diǎn)擊了進(jìn)入應(yīng)用按鈕");
}else{
NSLog(@"點(diǎn)擊了取消");
}
}
completionHandler();
}
由此我們可以知道action,categroy,request這些東西都是通過各自的identifier獲取的。這樣可以很方便的定位到某一個(gè)通知或者action上,為交互的處理提供了很大的便利。
自定義通知樣式
在Xcode中File->New->Targe會(huì)出現(xiàn)下面的視圖

Notification Content對(duì)應(yīng)的是通知,Notification Service Extension對(duì)應(yīng)的是推送。我們這里要實(shí)現(xiàn)通知的自定義,選擇左邊那個(gè)。創(chuàng)建成功之后會(huì)在工程里多一個(gè)文件件

NotificationViewController文件是自動(dòng)生成的,里面有一個(gè)
- (void)didReceiveNotification:(UNNotification *)notification可以在這里定義一些通知的顯示。
MainInterface.storyboard文件是控制通知的storyboard文件,可以編輯需要的通知樣式。我們?cè)O(shè)計(jì)一下文字的顏色和顯示位置

接下來你可能會(huì)問,怎么把這個(gè)自定義的通知樣式應(yīng)用到當(dāng)前通知里呢?先別急,我們看下一個(gè)文件Info.flist里面的內(nèi)容

第一項(xiàng)UNNotificationExtensionCategory就是UNNotificationCategory的標(biāo)示,我們把他換成我們通知里使用的標(biāo)示"Category",系統(tǒng)就會(huì)自動(dòng)匹配通知顯示的樣式。
第二項(xiàng)UNNotificationExtensionIntialContentSizeRation初始內(nèi)容 Size 的比例。也可以在 viewDidLoad 中使用 self.preferredContentSize 直接設(shè)置 Size。
第三項(xiàng)UNNotificationExtensionDefaultContentHidden是否隱藏默認(rèn)內(nèi)容,如果設(shè)為YES,默認(rèn)內(nèi)容會(huì)被隱藏。
顯示的效果:

總結(jié)
至此,iOS通知部分的內(nèi)容就學(xué)完了,參考代碼:Demo。
參考文檔:
iOS10 User Notificaitons學(xué)習(xí)筆記
活久見的重構(gòu)-iOS10 UserNotificaiotns框架解析