大伙久等啦~這絕對是最全最詳細的 UNNotificationContentExtension講解喲~
這篇文章中,我會給大家補充完推送內容的後續部分,希望大家看完這篇文章後,便可以輕松的玩轉推送了。
1、UNNotificationContentExtension
1.1、UNNotificationContentExtension簡介
簡單來說,UNNotificationContentExtension這個類,也是iOS10推送的新特性,官方文檔用這麼一句話,簡單的解釋了一下,Presents a custom interface for a delivered local or remote notification.(當你收到遠程或者本地通知的時候,彈出一個自定義界面)。效果如下圖所示
還有下圖
上面的兩張圖就是我們將要做出的效果,在自定義View的區域,你可以放上個視頻,放上個日歷,放上個顯示地理位置的Label,總而言之,我們可以自定義View!
1.2、如何新建一個UNNotificationContentExtension
創建這個UNNotificationContentExtension的Target,類似於創建UNNotificationServiceExtension的步驟。
第一步:創建
第二步:選擇創建類型
之後便可以看到生成了這些內容
1.3、如何使用以及相關Demo
說到如何使用這個類,我們就一定要先說一下,系統幫我們生成的這幾個文件分別代表了什麼意思。
>0.Info.plist
在這個NSExtensionAttributes的字典下面,我們有三個屬性可以添加
1.UNNotificationExtensionCategory.
(必須要有,系統已經創建好)
解釋:對應這個key的值,可以是一個字符串,也可以是一個數組,每一個字符串都是一個identifier,這個identifier對應著每一個UNMutableNotificationContent的categoryIdentifier的屬性。
簡單來說,就是在收到通知的時候,我們可以讓服務器把這個通知的categoryIdentifier帶上,作用是,我們可以根據視頻,音樂,圖片,來分別自定義我們的通知內容。不同的分類標識符,也會在我們講到UNNotificationAction的時候,幫助我們區分是什麼類型的通知,方便我們對不同類型的通知做出不同的操作行為。上面的截圖中,我是一個字符串的形式。下圖為數組形式:
使用的時候,我們參照如下代碼:
// 1.這個方法是UNNotificationServiceExtension類裡面的方法,可以參照我上一篇文章講的UNNotificationServiceExtension,我要在這裡重寫我的通知。 - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; // copy發來的通知,開始做一些處理 self.bestAttemptContent = [request.content mutableCopy]; // Modify the notification content here... self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title]; // 重寫一些東西 self.bestAttemptContent.title = @"我是標題"; self.bestAttemptContent.subtitle = @"我是子標題"; self.bestAttemptContent.body = @"來自徐不同"; // 附件 NSDictionary *dict = self.bestAttemptContent.userInfo; NSDictionary *notiDict = dict[@"aps"]; NSString *imgUrl = [NSString stringWithFormat:@"%@",notiDict[@"imageAbsoluteString"]]; !!!!! 這裡是重點!!!!!!!!!!!! // 我在這裡寫死了category1,其實在收到系統推送時,每一個推送內容最好帶上一個catagory,跟服務器約定好了,這樣方便我們根據categoryIdentifier來自定義不同類型的視圖,以及action self.bestAttemptContent.categoryIdentifier = @"category1"; }
大家注意上面的
!!!!! 這裡是重點!!!!!!!!!!!! // 我在這裡寫死了category1,其實在收到系統推送時,每一個推送內容最好帶上一個catagory,跟服務器約定好了,這樣方便我們根據categoryIdentifier來自定義不同類型的視圖,以及action self.bestAttemptContent.categoryIdentifier = @"category1";
這裡設置categoryIdentifier,最好讓服務器的推送內容帶上這個,然後我們好更加的定制化。不建議本地寫死。
具體可以參考我的demo地址
2.UNNotificationExtensionInitialContentSizeRatio.
(必須要有,系統已經創建好)
解釋:這個值的類型是一個浮點類型,代表的是高度與寬度的比值。系統會使用這個比值,作為初始化view的大小。舉個簡單的例子來說,如果該值為1,則該視圖為正方
形。如果為0.5,則代表高度是寬度的一半。
注意這個值只是初始化的一個值,在這個擴展添加後,可以重寫frame,展示的時候,在我們還沒打開這個視圖預覽時,背景是個類似圖片占位的灰色,那個灰色的高度寬度
之比,就是通過這個值來設定。
3.UNNotificationExtensionDefaultContentHidden.
(可選)
解釋:這個值是一個BOOL值,當為YES時,會隱藏上方原本推送的內容視圖,只會顯示我們自定義的視圖。(因為在自定義視圖的時候,我們可以取得推送內容,然後按照我們想要的布局,展示出來)如果為NO時(默認為NO),推送視圖就會既有我們的自定義視圖,也會有系統原本的推送內容視圖(這裡附件是不會顯示的,只會顯示body裡面的文字喲)
4.至於NSExtensionMainStoryboard以及NSExtensionPointIdentifier,系統默認生成,大家直接用就好,如果需要更改的,只能更改使用的storyboard的名字(不過應該沒人會把系統的刪除在建立一個吧 O(∩_∩)O)
MainInterface.storyboard
這個就是個簡單的storyboard文件,內部有一個View,這個View就是在上面的圖層中的自定義View視圖了。它與NotificationViewController所綁定。
NotificationViewController
這是是系統幫我們默認創建了一個控制器,繼承UIViewController,其實就是一個控制器啦。
說道這個控制器我們需要講解一個方法:
遵守UNNotificationContentExtension的協議,我們需要用到一下的方法
// 這個方法是說,只要你收到通知,並且保證categoryIdentifier的設置,跟info.plist裡面設置的一樣,你就會調用這個方法。注意:一個會話的多個通知,每個通知收到時,都可以調用這個方法。- (void)didReceiveNotification:(UNNotification *)notification;
使用如下:
- (void)didReceiveNotification:(UNNotification *)notification { 這個方法,可以給自己的控件賦值啊,調整frame啊等等,我在這裡打印出來了通知的內容,供大家使用。 NSDictionary *dict = notification.request.content.userInfo; // 這裡可以把打印的所有東西拿出來 NSLog(@"%@",dict); /****************************打印的信息是************ aps = { alert = "This is some fancy message."; badge = 1; from = "大家好,我是徐不同"; imageAbsoluteString = "http://upload.univs.cn/2012/0104/1325645511371.jpg"; "mutable-content" = 1; sound = default; }; } *******************************************/ }
說到這裡,簡單的UNNotificationContentExtension已經說完了,我在給大家補充一點。在UNNotificationContentExtension.h中,有著這麼一個枚舉
typedef NS_ENUM(NSUInteger, UNNotificationContentExtensionMediaPlayPauseButtonType) { // 沒有播放按鈕 UNNotificationContentExtensionMediaPlayPauseButtonTypeNone, // 有播放按鈕,點擊播放之後,按鈕依舊存在,類似音樂播放的開關 UNNotificationContentExtensionMediaPlayPauseButtonTypeDefault, // 有播放按鈕,點擊後,播放按鈕消失,再次點擊暫停播放後,按鈕恢復 UNNotificationContentExtensionMediaPlayPauseButtonTypeOverlay, }
看到這麼枚舉,大家一定納悶怎麼使用啊。請看下面的幾個屬性
// 設置播放按鈕的屬性 @property (nonatomic, readonly, assign) UNNotificationContentExtensionMediaPlayPauseButtonType mediaPlayPauseButtonType; // 設置播放按鈕的frame @property (nonatomic, readonly, assign) CGRect mediaPlayPauseButtonFrame; // 設置播放按鈕的顏色 @property (nonatomic, readonly, copy) UIColor *mediaPlayPauseButtonTintColor; // 開始跟暫停播放 - (void)mediaPlay; - (void)mediaPause;
還有以下的類,這個類雖然也有開始播放跟結束播放的方法,不過要注意,這個是屬於NSExtensionContext的,而上面我們講的方法是UNNotificationContentExtension協議方法裡的。大家要注意。
@interface NSExtensionContext (UNNotificationContentExtension) // 控制播放 - (void)mediaPlayingStarted // 控制暫停 - (void)mediaPlayingPaused @end
看到這些屬性,想要知道如何使用,請看我下面的步驟:
分析:
首先這些屬性都是readonly的,所以直接用self.屬性去修改肯定是報錯的,所以我們能用的就只有get方法了。
其次:根據button的類型,我們可以聯想到,如果button沒有,這個播放開始暫停的方法也沒用了。如果有button,自然我們就有了播放的操作,聯想別的UI空間,我們得出了一定要重寫它的frame,來確定他的位置。設置顏色,來設置它的顯示顏色。設置button的類型,讓他顯示出來。
// 返回默認樣式的button - (UNNotificationContentExtensionMediaPlayPauseButtonType)mediaPlayPauseButtonType { return UNNotificationContentExtensionMediaPlayPauseButtonTypeDefault; } // 返回button的frame - (CGRect)mediaPlayPauseButtonFrame { return CGRectMake(100, 100, 100, 100); } // 返回button的顏色 - (UIColor *)mediaPlayPauseButtonTintColor{ return [UIColor blueColor]; }
通過上面的代碼,我們的button已經可以顯示出來了。如下圖(請忽略下面的策略等按鈕):
具體位置,大家可以通過重寫frame來確定button的位置。
當我們點擊這個藍色button的時候,便可以執行一些播放暫停操作了,如下
- (void)mediaPlay{ NSLog(@"mediaPlay,開始播放"); } - (void)mediaPause{ NSLog(@"mediaPause,暫停播放"); }
說道這裡,還少說一個地方,那就是NSExtensionContext類的播放暫停事件我們需要什麼時候調用呢?
經過我的研究,可以這麼使用,如下
- (void)mediaPlay{ NSLog(@"mediaPlay,開始播放"); // 點擊播放按鈕後,4s後暫停播放 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.extensionContext mediaPlayingPaused]; }); } - (void)mediaPause{ NSLog(@"mediaPause,暫停播放"); // 點擊暫停按鈕,10s後開始播放 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.extensionContext mediaPlayingStarted]; }); }
這裡需要說幾個注意點
1.在這個控制器中,我們可以直接電泳self.extensionContext,來調用它的播放暫停方法。
2.調用這個播放暫停方法,並不會重新調用- (void)mediaPlay{}或者- (void)mediaPause{},只能單純的調用。經過我的測試,
- (void)mediaPlayingStarted{ NSLog(@"主動調用開始的方法"); } - (void)mediaPlayingPaused { NSLog(@"主動調用暫停的方法"); }
用上述代碼,是監聽不到方法點擊的喲~
有了自定義內容,自然也就有了自定義的action(行為),我明日補上~謝謝大家咯~
重要的事情說三遍,demo地址
重要的事情說三遍,demo地址
重要的事情說三遍,demo地址