<pre>上一篇中講到Message中的一些特性拼弃,本次主要講下Notification的特性</pre>
iOS10相對于之前的版本夏伊,主要是開發(fā)者可以使用Extension的形式修改和展示內(nèi)容,主要是<code>UNNotificationServiceExtension</code>和<code>UNNotificationContentExtension</code>吻氧。同時也添加了其他方面的支持溺忧,例如<code>UNNotificationTrigger</code>、<code>UNNotificationAttachment</code>盯孙、<code>UNNotificationAction</code>鲁森。本次講的主要有以下幾點(diǎn):
- UNNotificationTrigger(通知觸發(fā)條件設(shè)定)
- UNNotificationAttachment (通知附件)
- UNNotificationContentExtension (通知內(nèi)容擴(kuò)展)
- UNNotificationServiceExtension (通知服務(wù)擴(kuò)展)
- UNNotificationAction (通知響應(yīng)事件)
1、UNNotificationTrigger(通知觸發(fā)條件設(shè)定)
主要是針對本地通知觸發(fā)時機(jī)的設(shè)置振惰,可以使用下面方式設(shè)置:
- UNPushNotificationTrigger:這個是蘋果通知服務(wù)的 Trigger歌溉,對外沒有暴露任何接口屬性,不需要開發(fā)者創(chuàng)建报账,由系統(tǒng)創(chuàng)建研底。
- UNTimeIntervalNotificationTrigger(時間觸發(fā)器):通過初始化方法設(shè)置通知的timeInterval(觸發(fā)間隔)
和repeats(是否重復(fù)觸發(fā)),若 repeats 設(shè)置為 false透罢,通知將在 timeInterval 之后被推送榜晦。 - UNCalendarNotificationTrigger(日期觸發(fā)器):類似 UNTimeIntervalNotificationTrigger,也是時間觸發(fā)器羽圃,只不過初始化時第一個參數(shù)為 DateComponents類型乾胶,可設(shè)置具體的觸發(fā)時間比如8:00 AM等,也可設(shè)置是否重復(fù)觸發(fā)朽寞。
- UNLocationNotificationTrigger(位置觸發(fā)器):通過設(shè)置 CLRegion類型參數(shù)設(shè)置位置信息识窿,當(dāng)用戶處于某一區(qū)域時,自動推送通知脑融。
使用:
//設(shè)置Notification內(nèi)容
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:@"title!" arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:@"body" arguments:nil];
content.subtitle = [NSString localizedUserNotificationStringForKey:@"subtitle" arguments:nil];
content.sound = [UNNotificationSound defaultSound];
//初始化時間觸發(fā)器
UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:10 repeats:NO];
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"Identifier"
content:content
trigger:trigger];
// 請求計劃推送
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if(error)
{
NSLog(@"%@",error);
}
}];
2喻频、UNNotificationAttachment(通知附件)
蘋果所支持的推送附件類型包含視頻,音頻肘迎,圖片甥温,蘋果的文檔中對文件的類型和大小做了如下限制:傳送門
使用說明:
- 本地通知:
設(shè)置<code>UNMutableNotificationContent</code>如下屬性
@property (NS_NONATOMIC_IOSONLY, copy) NSArray <UNNotificationAttachment *> *attachments```
- 遠(yuǎn)程通知:
通過URL地址下載資源,然后將資源設(shè)置到
request.content.attachments
中示例代碼:
- (void)handlerImageWith:(NSString *)attachUrl{
[self downloadFileAndSave:[NSURL URLWithString:attachUrl] handler:^(NSURL *localUrl) {
if (localUrl){
UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"image_download" URL:localUrl options:nil error:nil];
self.bestAttemptContent.attachments = @[attachment];
}
self.contentHandler(self.bestAttemptContent);
}];
}
- (void)downloadFileAndSave:(NSURL *)url handler:(void (^)(NSURL *))handler{
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url
completionHandler:^(NSURL * _Nullable location,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
NSURL *localURL = nil;
if(!error){
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// response.suggestedFilename : 建議使用的文件名妓布,一般跟服務(wù)器端的文件名一致
NSString *file = [caches stringByAppendingPathComponent:response.suggestedFilename];
// 將臨時文件剪切或者復(fù)制Caches文件夾
NSFileManager *mgr = [NSFileManager defaultManager];
// AtPath : 剪切前的文件路徑
// ToPath : 剪切后的文件路徑
[mgr moveItemAtPath:location.path toPath:file error:nil];
if (file && ![file isEqualToString: @""])
{
localURL = [NSURL URLWithString:[@"file://" stringByAppendingString:file]];
}
}
handler(localURL);
}];
[downloadTask resume];
}
注意事項(xiàng):
- UNNotificationContent 的 attachments雖然是一個數(shù)組姻蚓,但是系統(tǒng)只會展示第一個 attachment 對象的內(nèi)容。不過你依然可以發(fā)送多個 attachments匣沼,然后在要展示的時候再重新安排它們的順序狰挡,以顯示最符合情景的圖片或者視頻。另外释涛,你也可能會在自定義通知展示 UI 時用到多個 attachment加叁。
- 在當(dāng)前 beta (iOS 10 beta 4) 中,serviceExtensionTimeWillExpire被調(diào)用之前枢贿,你有 30 秒時間來處理和更改通知內(nèi)容殉农。對于一般的圖片來說,這個時間是足夠的局荚。但是如果你推送的是體積較大的視頻內(nèi)容超凳,用戶又恰巧處在糟糕的網(wǎng)絡(luò)環(huán)境的話,很有可能無法及時下載完成耀态。
- 如果你想在遠(yuǎn)程推送來的通知中顯示應(yīng)用 bundle 內(nèi)的資源的話轮傍,要注意 extension 的 bundle 和 app main bundle 并不是一回事兒。你可以選擇將圖片資源放到 extension bundle 中首装,也可以選擇放在 main bundle 里创夜。總之仙逻,你需要保證能夠獲取到正確的驰吓,并且你具有讀取權(quán)限的 url涧尿。關(guān)于從 extension 中訪問 main bundle,可以參看這篇回答檬贰。
- 系統(tǒng)在創(chuàng)建 attachement 時會根據(jù)提供的 url 后綴確定文件類型姑廉,如果沒有后綴,或者后綴無法不正確的話翁涤,你可以在創(chuàng)建時通過 UNNotificationAttachmentOptionsTypeHintKey
來指定資源類型桥言。 - 如果使用的圖片和視頻文件不在你的 bundle 內(nèi)部,它們將被移動到系統(tǒng)的負(fù)責(zé)通知的文件夾下葵礼,然后在當(dāng)通知被移除后刪除号阿。如果媒體文件在 bundle 內(nèi)部,它們將被復(fù)制到通知文件夾下鸳粉。每個應(yīng)用能使用的媒體文件的文件大小總和是有限制扔涧,超過限制后創(chuàng)建 attachment 時將拋出異常×扪希可能的所有錯誤可以在 UNError中找到扰柠。
- 你可以訪問一個已經(jīng)創(chuàng)建的 attachment 的內(nèi)容,但是要注意權(quán)限問題疼约÷钡担可以使用 startAccessingSecurityScopedResource來暫時獲取以創(chuàng)建的 attachment 的訪問權(quán)限。比如:
if(notification.request.content.attachments && notification.request.content.attachments.count > 0){
NSURL *imageUrl = notification.request.content.attachments[0].URL;
if([imageUrl startAccessingSecurityScopedResource]){
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
UIImage *image = [[UIImage alloc] initWithData:imageData];
self.imageView.image = image;
[imageUrl stopAccessingSecurityScopedResource];
}
}
3程剥、UNNotificationContentExtension(通知內(nèi)容擴(kuò)展)
通知內(nèi)容擴(kuò)展需要新建一個 UNNotificationContentExtension Target劝枣,之后只需在 viewcontroller 的中實(shí)現(xiàn)相應(yīng)的接口,即可以對 app 的通知頁面進(jìn)行自定義擴(kuò)展织鲸,擴(kuò)展主要用于自定義 UI舔腾。擴(kuò)展頁面樣式可以在 plist 中配置,字段說明如下:
- UNNotificationExtensionCategory: 要讓通知支持內(nèi)容擴(kuò)展搂擦,需要將通知的 categoryIdentifier(類型標(biāo)示) 加入此處稳诚。
- UNNotificationExtensionDefaultContentHidden: 默認(rèn)內(nèi)容隱藏,如果設(shè)為 YES瀑踢,則最下面通知 content 部分會隱藏扳还。
- UNNotificationExtensionIntialContentSizeRation: 初始內(nèi)容 Size 的比例。也可以在 viewDidLoad 中使用 self.preferredContentSize 直接設(shè)置 Size橱夭。
使用說明:
遠(yuǎn)程和本地通知最終都可以使用此擴(kuò)展自定義 UI氨距,只需將通知的 categoryIdentifier(類型標(biāo)示) 加入到 plist 中即可。
- 本地推送時棘劣,確保設(shè)置的 content.categoryIdentifier(通知內(nèi)容類型標(biāo)示) 已加入 plist 中俏让。
- 遠(yuǎn)程推送,需要設(shè)置 category 字段,且確保值也已加入 plist 中首昔。
4寡喝、UNNotificationServiceExtension (通知服務(wù)擴(kuò)展)
UNNotificationServiceExtension 提供在遠(yuǎn)程推送將要被 push 出來前,處理推送顯示內(nèi)容的機(jī)會勒奇。此時可以對通知的 request.content 進(jìn)行內(nèi)容添加拘荡,如添加附件,userInfo 等撬陵。服務(wù)器推送實(shí)例:
{
"aps" : {
"alert" : {
"title" : "title",
"body" : "Your message Here"
},
// 開啟可變內(nèi)容
"mutable-content" : "1",
// 加入自定義數(shù)據(jù),圖片 url 路徑
"image":"http://....jpg"
}
}
示例代碼:
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
NSDictionary *apsDic = [request.content.userInfo objectForKey:@"aps"];
NSString *attachUrl = [apsDic objectForKey:@"image"];
if(attachUrl){
[self handlerImageWith:attachUrl];
}
}
5网缝、UNNotificationAction(通知響應(yīng)事件)
代表一個響應(yīng)通知的事件巨税。可以為每個通知設(shè)置不同的交互事件粉臊。下拉推送通知或處在鎖屏界面?zhèn)然ㄖ獣r草添,會出現(xiàn)交互按鍵。
交互事件主要分為以下兩類:
-
UNNotificationAction:
普通點(diǎn)擊按鍵扼仲,可設(shè)置 identifier远寸、 title 及 點(diǎn)擊后的響應(yīng),例如:foreground 前臺響應(yīng)屠凶,destructive 點(diǎn)擊后銷毀通知驰后,authenticationRequired 響應(yīng)前是否需要解鎖。甚至可以使用 UNNotificationAction + accessoryInputView 結(jié)合矗愧,達(dá)到加入自定義輔助輸入控件的效果 -
UNTextInputNotificationAction:
當(dāng)然也可以直接使用系統(tǒng)類 UNTextInputNotificationAction 創(chuàng)建輸入框灶芝,但是風(fēng)格比較固定。
示例代碼:
- (void)registerNotificationCategory{
UNTextInputNotificationAction *inputAction = [UNTextInputNotificationAction actionWithIdentifier:@"action_reply" title:@"回復(fù)" options:UNNotificationActionOptionForeground];
UNNotificationAction *cancelAction = [UNNotificationAction actionWithIdentifier:@"action_cancel" title:@"取消" options:UNNotificationActionOptionDestructive];
UNNotificationCategory *saySomething = [UNNotificationCategory categoryWithIdentifier:saySomethingCategory actions:@[inputAction,cancelAction] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObject:saySomething]];
}
響應(yīng)處理:
- 若處于 UNNotificationContentExtension 通知擴(kuò)展界面時唉韭,點(diǎn)擊 【回復(fù)】按鍵會回調(diào) UNNotificationContentExtension 擴(kuò)展接口的方法:
// If implemented, the method will be called when the user taps on one
// of the notification actions. The completion handler can be called
// after handling the action to dismiss the notification and forward the
// action to the app if necessary.
- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(UNNotificationContentExtensionResponseOption option))completion;{
}
- 如果不支持 UNNotificationContentExtension則點(diǎn)擊【回復(fù)】回調(diào) UNUserNotificationCenterDelegate 中的方法:
// The method will be called on the delegate when the user responded to the notification by opening the application, dismissing the notification or choosing a UNNotificationAction. The delegate must be set before the application returns from applicationDidFinishLaunching:.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
}
補(bǔ)充:iOS10中可以在前臺中收到通知了夜涕,需要添加一下代碼:
\\ notificationHandler實(shí)現(xiàn)UNUserNotificationCenterDelegate
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self.notificationHandler];