iOS 10?中添加了兩個與通知相關(guān)的?extension:Service Extension?和?Content Extension枣申。前者我在上文中已經(jīng)介紹過了讼呢,本文介紹下后者:可以用來自定義通知的詳細(xì)頁面視圖的?Content Extension蔗怠。
十五、創(chuàng)建 Notification Content Extension
1逃糟,操作步驟
(1)首先我們點(diǎn)擊"File" -> "New" -> "Target..."捷绑,使用?NotificationContent?的模板來創(chuàng)建一個?NotificationContent。
(2)使用模版創(chuàng)建完畢后劫谅,會自動生成如下三個文件:
(3)NotificationViewController.swift
這個是一個實現(xiàn)了?UNNotificationContentExtension?的?UIViewController?子類见坑。
該?extension?中有一個必須實現(xiàn)的方法?didReceive(_:)。當(dāng)系統(tǒng)需要顯示自定義樣式的通知詳情視圖時捏检,這個方法將被調(diào)用荞驴,然后我們可以在其中配置更新我們的?UI。
默認(rèn)生成的代碼如下:直接將通知內(nèi)容顯示在?label?中贯城。我們先不做修改熊楼。
import?UIKit
import?UserNotifications
import?UserNotificationsUI
class?NotificationViewController:?UIViewController,?UNNotificationContentExtension?{
????@IBOutlet?var?label:?UILabel?
????override?func?viewDidLoad() {
????????super.viewDidLoad()
????}
????func?didReceive(_ notification:?UNNotification) {
????????self.label?.text = notification.request.content.body
????}
}
(4)MainInterface.storyboard
這里定義了該?extension?對應(yīng)的詳情視圖?UI。
默認(rèn)生成的?UI?如下:只有一個?label?文本標(biāo)簽能犯。我們先不做修改鲫骗。
(5)Info.plist
這里指定了該?extension?的各種配置。我們可以通過?Info.plist?控制通知詳細(xì)視圖的尺寸踩晶,以及是否顯示原始的通知执泰。
要特別注意的是?UNNotificationExtensionCategory?這個?key?值,它指定這個通知樣式所對應(yīng)的?category?標(biāo)識符渡蜻。系統(tǒng)在接收到通知后會通過?category?標(biāo)識符先查找有沒有能夠處理這類通知的?content extension术吝,如果存在,那么就交給這個extension?來進(jìn)行處理茸苇。
默認(rèn)生成的?category?標(biāo)識符是?myNotificationCategory排苍。我們先不做修改。
2学密,使用樣例
(1)下面代碼在頁面加載完畢后會自動創(chuàng)建個?5?秒后的推送通知淘衙。注意的是我們將通知的?categoryIdentifier?設(shè)置成上面?content extension?的?category?標(biāo)識符。
import?UIKit
import?UserNotifications
class?ViewController:?UIViewController?{
????override?func?viewDidLoad() {
????????super.viewDidLoad()
????????//設(shè)置推送內(nèi)容
????????let?content =?UNMutableNotificationContent()
????????content.title =?"hangge.com"
????????content.body =?"做最好的開發(fā)者知識平臺"
????????//設(shè)置category標(biāo)識符
????????content.categoryIdentifier =?"myNotificationCategory"
????????//設(shè)置通知觸發(fā)器
????????let?trigger =?UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats:?false)
????????//設(shè)置請求標(biāo)識符
????????let?requestIdentifier =?"com.hangge.testNotification"
????????//設(shè)置一個通知請求
????????let?request =?UNNotificationRequest(identifier: requestIdentifier,
????????????????????????????????????????????content: content, trigger: trigger)
????????//將通知請求添加到發(fā)送中心
????????UNUserNotificationCenter.current().add(request) { error?in
????????????if?error ==?nil?{
????????????????print("Time Interval Notification scheduled: \(requestIdentifier)")
????????????}
????????}
????}
????override?func?didReceiveMemoryWarning() {
????????super.didReceiveMemoryWarning()
????}
}
(2)可以看到通知的詳情視圖已經(jīng)變成我們自定義的視圖了则果。
十六幔翰、自定義通知詳情視圖(并添加 UI 交互功能)
1,效果圖
(1)這里我們推送一條使用自定義詳情視圖的通知西壮,這個通知里其實包含了三條新聞資訊遗增。
(2)打開通知詳情時,會顯示第一條資訊的標(biāo)題款青、內(nèi)容摘要做修、以及相關(guān)圖片牡整。下方還有三個交互按鈕:
點(diǎn)擊“換一條”按鈕慷蠕,這個通知視圖會繼續(xù)顯示,不過內(nèi)容會切換成下一條資訊。
點(diǎn)擊“打開”按鈕欺殿,則自動打開應(yīng)用再沧。我們可以在程序中進(jìn)行下一步操作饶囚,比如打開對應(yīng)的新聞詳情頁面军援。
點(diǎn)擊”取消“按鈕,則自動清除通知屏箍,且不會打開應(yīng)用绘梦。
2,Notification Content Extension 配置
(1)MainInterface.storyboard
這里我們在視圖上添加兩個?Label?和一個?ImageView赴魁,分別用來顯示新聞資訊的標(biāo)題卸奉、內(nèi)容摘要、以及圖片颖御。
同時還要設(shè)置好各個組件的約束榄棵,并在代碼中做好?@IBOutlet?關(guān)聯(lián)。
(2)NotificationViewController.swift
我們在這里對詳情視圖進(jìn)行顯示和更新操作潘拱。特別注意的是疹鳄,雖然我們可以使用包括按鈕在內(nèi)的各種?UI?組件,但是系統(tǒng)不允許我們與這些?UI?進(jìn)行交互芦岂。點(diǎn)擊通知視圖本身會直接將我們導(dǎo)航到應(yīng)用中尚辑,因此我們需要通過?action?按鈕的方式來對視圖進(jìn)行更新。
didReceive(_:completionHandler:)方法介紹:
它是?UNNotificationContentExtension?的一個可選方法盔腔,它會在用戶選擇了某個?action?時被調(diào)用。我們可以根據(jù)情況給?completionHandler?傳遞不同的值實現(xiàn)不同操作:
如果需要更新詳情視圖月褥,可以選擇傳遞?.doNotDismiss?來保持通知繼續(xù)被顯示弛随。
如果沒有繼續(xù)顯示的必要,傳遞?.dismissAndForwardAction?會打開應(yīng)用宁赤,并把通知的?action?繼續(xù)傳遞給應(yīng)用的?UNUserNotificationCenterDelegate?中的?userNotificationCenter(:didReceive:withCompletionHandler)
而傳遞?.dismiss則直接將這個通知清除舀透,同時也不會打開這個應(yīng)用。
import?UIKit
import?UserNotifications
import?UserNotificationsUI
//資訊條目
struct?NewsItem?{
????let?title:?String
????let?abstract:?String
????let?url:?URL
}
class?NotificationViewController:?UIViewController,?UNNotificationContentExtension?{
????//顯示資訊標(biāo)題
????@IBOutlet?var?titleLabel:?UILabel!
????//顯示資訊內(nèi)容摘要
????@IBOutlet?weak?var?abstractLabel:?UILabel!
????//顯示資訊圖片
????@IBOutlet?weak?var?imageView:?UIImageView!
????//當(dāng)前顯示的資訊索引
????private?var?index:?Int?= 0
????//所有資訊條目
????var?items: [NewsItem] = []
????override?func?viewDidLoad() {
????????super.viewDidLoad()
????}
????//收到通知
????func?didReceive(_ notification:?UNNotification) {
????????//處理資訊條目
????????let?content = notification.request.content
????????if?let?news = content.userInfo["news"]?as? [[String:?String]] {
????????????for?i?in?0..<news.count {
????????????????let?title = news[i]["title"] ???""
????????????????let?abstract = news[i]["abstract"] ???""
????????????????let?url = content.attachments[i].url
????????????????let?presentItem =?NewsItem(title: title, abstract: abstract, url: url)
????????????????self.items.append(presentItem)
????????????}
????????}
????????//顯示第一條資訊
????????updateNews(index: 0)
????}
????//更新顯示的資訊內(nèi)容
????private?func?updateNews(index:?Int) {
????????let?item = items[index]
????????//更新標(biāo)題和內(nèi)容摘要
????????self.titleLabel!.text = item.title
????????self.abstractLabel.text = item.abstract
????????//更新圖片
????????if?item.url.startAccessingSecurityScopedResource() {
????????????self.imageView.image =?UIImage(contentsOfFile: item.url.path)
????????????item.url.stopAccessingSecurityScopedResource()
????????}
????????self.index = index
????}
????//Action按鈕點(diǎn)擊響應(yīng)
????func?didReceive(_ response:?UNNotificationResponse, completionHandler completion:
????????@escaping?(UNNotificationContentExtensionResponseOption) ->?Void) {
????????if?response.actionIdentifier ==?"change"?{
????????????//切換下一條資訊
????????????let?nextIndex = (index + 1) % items.count
????????????updateNews(index: nextIndex)
????????????//保持通知繼續(xù)被顯示
????????????completion(.doNotDismiss)
????????}?else?if?response.actionIdentifier ==?"open"?{
????????????//取消這個通知并繼續(xù)傳遞Action
????????????completion(.dismissAndForwardAction)
????????}?else?if?response.actionIdentifier ==?"dismiss"?{
????????????//直接取消這個通知
????????????completion(.dismiss)
????????}?else?{
????????????//取消這個通知并繼續(xù)傳遞Action
????????????completion(.dismissAndForwardAction)
????????}
????}
}
(3)extension?的?Info.plist
通知擴(kuò)展對應(yīng)的?category?標(biāo)識符這里不做修改决左。主要修改下?UNNotificationExtensionInitialContentSizeRatio?這個?key?值愕够,它是?UI?界面默認(rèn)的高寬比,將其修改成?0.8佛猛,這樣在界面出來的時候不會有很突兀的?frame?改變惑芭。
3,Notification Content Extension 使用
(1)AppDelegate.swift
這里要注意的是我們注冊一個通知?category继找,里面包含三個?Action?按鈕遂跟。
import?UIKit
import?UserNotifications
@UIApplicationMain
class?AppDelegate:?UIResponder,?UIApplicationDelegate?{
????var?window:?UIWindow?
????func?application(_ application:?UIApplication, didFinishLaunchingWithOptions
????????launchOptions: [UIApplicationLaunchOptionsKey:?Any]?) ->?Bool?{
????????UNUserNotificationCenter.current()
????????????.requestAuthorization(options: [.alert, .sound, .badge]) {
????????????????(accepted, error)?in
????????????if?!accepted {
????????????????print("用戶不允許消息通知。")
????????????}
????????}
????????//注冊category
????????registerNotificationCategory()
????????return?true
????}
????func?applicationWillResignActive(_ application:?UIApplication) {
????}
????func?applicationDidEnterBackground(_ application:?UIApplication) {
????}
????func?applicationWillEnterForeground(_ application:?UIApplication) {
????}
????func?applicationDidBecomeActive(_ application:?UIApplication) {
????}
????func?applicationWillTerminate(_ application:?UIApplication) {
????}
????//注冊一個category
????private?func?registerNotificationCategory() {
????????let?newsCategory:?UNNotificationCategory?= {
????????????//創(chuàng)建三個普通的按鈕action
????????????let?changeAction =?UNNotificationAction(
????????????????identifier:?"change",
????????????????title:?"換一條",
????????????????options: [])
????????????let?openAction =?UNNotificationAction(
????????????????identifier:?"open",
????????????????title:?"打開",
????????????????options: [.foreground])
????????????//創(chuàng)建普通的按鈕action
????????????let?cancelAction =?UNNotificationAction(
????????????????identifier:?"cancel",
????????????????title:?"取消",
????????????????options: [.destructive])
????????????//創(chuàng)建category
????????????return?UNNotificationCategory(identifier:?"myNotificationCategory",
??????????????????????????????????????????actions: [changeAction, openAction, cancelAction],
??????????????????????????????????????????intentIdentifiers: [], options: [])
????????}()
????????//把category添加到通知中心
????????UNUserNotificationCenter.current().setNotificationCategories([newsCategory])
????}
}
(2)ViewController.swift
我們同樣是頁面打開后就推送個?5?秒后的通知。注意的是這里會給通知添加附加信息(包含資訊標(biāo)題和內(nèi)容摘要)幻锁,以及資訊使用的圖片附件凯亮。
import?UIKit
import?UserNotifications
class?ViewController:?UIViewController?{
????override?func?viewDidLoad() {
????????super.viewDidLoad()
????????//設(shè)置推送內(nèi)容
????????let?content =?UNMutableNotificationContent()
????????content.body =?"今日資訊精選【2017-12-12】"
????????//設(shè)置通知category標(biāo)識符
????????content.categoryIdentifier =?"myNotificationCategory"
????????//設(shè)置通知附件圖片
????????let?imageNames = ["image1",?"image2",?"image3"]
????????let?attachments = imageNames.flatMap { name ->?UNNotificationAttachment??in
????????????if?let?imageURL =?Bundle.main.url(forResource: name, withExtension:?"png") {
????????????????return?try??UNNotificationAttachment(identifier:?"\(name)", url: imageURL,
?????????????????????????????????????????????????????options:?nil)
????????????}
????????????return?nil
????????}
????????content.attachments = attachments
????????//設(shè)置通知附加信息(資訊標(biāo)題和內(nèi)容摘要)
????????content.userInfo = ["news": [
????????????["title":?"全國人民喜迎油價上漲",
?????????????"abstract":?"據(jù)國內(nèi)多家測評機(jī)構(gòu)的分析,國內(nèi)成品油零售限價將迎來“兩連漲”..."],
????????????["title":?"房價同比下降城市大幅擴(kuò)容",
?????????????"abstract":?"70個大中城市中一二三線城市房價同比漲幅繼續(xù)回落哄尔。這意味著假消,往年..."],
????????????["title":?"比特幣市值再創(chuàng)新高",
?????????????"abstract":?"一項名為SegWit2X的技術(shù)取消升級,導(dǎo)致在本周一比特幣市值蒸發(fā)多達(dá)380億美元..."]
????????????]]
????????//設(shè)置通知觸發(fā)器
????????let?trigger =?UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats:?false)
????????//設(shè)置請求標(biāo)識符
????????let?requestIdentifier =?"com.hangge.testNotification"
????????//設(shè)置一個通知請求
????????let?request =?UNNotificationRequest(identifier: requestIdentifier,
????????????????????????????????????????????content: content, trigger: trigger)
????????//將通知請求添加到發(fā)送中心
????????UNUserNotificationCenter.current().add(request) { error?in
????????????if?error ==?nil?{
????????????????print("Time Interval Notification scheduled: \(requestIdentifier)")
????????????}
????????}
????}
????override?func?didReceiveMemoryWarning() {
????????super.didReceiveMemoryWarning()
????}
}
原文出自:www.hangge.com??轉(zhuǎn)載請保留原文鏈接:https://www.hangge.com/blog/cache/detail_1855.html