文章結構:
<a id="1"></a>前言
這階段在學習有關 iOS 10 消息推送的內容,通過查閱資料并親身實踐,對消息推送有了一定的理解姚糊。因此寫這篇文章,希望對剛接觸 iOS 消息推送的開發(fā)者有幫助授舟。
Apple 應用的消息推送分為本地消息推送(Local Notification)和遠程消息推送(Remote Notification)救恨。當有新的消息時,可以通過本地或遠程推送告知用戶释树,即使 App 并未運行肠槽。
- 本地消息推送不需要聯(lián)網(wǎng),由系統(tǒng)統(tǒng)一管理 App 推送的消息奢啥,App 只需與系統(tǒng)交互即可秸仙。本地消息推送適用于 iOS、tvOS 和 watchOS桩盲。
- 遠程消息推送需要連接網(wǎng)絡寂纪,通過 App 或者后臺服務器與 Apple Push Notification(APN) 通信,再由 APN 將消息推送到終端上。遠程消息推送除了支持 iOS捞蛋、tvOS 和 watchOS孝冒,還支持 macOS。
本文將大體介紹消息推送的相關內容拟杉,并實現(xiàn)基本的本地消息推送庄涡。想直接看如何實現(xiàn)本地消息推送,請看“本地消息推送實現(xiàn)”部分捣域。
<a id="2"></a>iOS 消息推送的基礎知識
<a id="21"></a>推送方式
盡管消息推送方式分為本地和遠程啼染,但是他們展現(xiàn)給用戶的方式是一樣的,因為它們默認使用的是系統(tǒng)提供的外觀焕梅。主要的推送方式有:
- 通知迹鹅、橫幅
- 應用圖標標記
- 帶有聲音的通知、橫幅或標記
<a id="22"></a>管理消息推送
App must be configured at launch time to support local and remote notification.
首先贞言,我們需要在 applicationDidFinishLaunching:
之前聲明支持消息推送的方式斜棚。如果想在 App 運行后某個時間再進行聲明的話,在此之前要避免推送消息该窗。因為在聲明支持消息推送之前弟蚀,發(fā)送任何消息都是無效的。
當配置了消息推送的方式后酗失,需要請求授權:requestAuthorizationWithOptions:completionHandler:
义钉,第一次調用該方法時,系統(tǒng)會提示用戶 App 需要推送消息规肴,等待用戶確認捶闸。系統(tǒng)自動保存用戶的授權結果,當以后調用該方法時拖刃,就不會在出現(xiàn)提示了删壮。
獲得推送消息權限后,就需要考慮以下幾個問題:
一兑牡、設定 Category央碟。當 App 推送的消息很多,需要進行分類時均函,就需要設定 Category亿虽。
let generalCategory = UNNotificationCategory(identifier: "GENERAL",actions: [],intentIdentifiers: [],options: .customDismissAction)
// Register the category.
let center = UNUserNotificationCenter.current()
center.setNotificationCategories([generalCategory])
設定消息的 Category 后,就可以添加自定義的行為(action)边酒,這樣用戶就可以在不打開 App 的情況下经柴,對消息進行簡單的操作。如果不為消息分配 Category墩朦,那么消息就會以默認的形式推送坯认,不帶有任何附加的行為。
二、為 Category 添加自定義的行為牛哺。每個 Category 最多可以包含四個自定義的行為陋气。
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])
三、配置通知聲音引润。本地和遠程推送都可以自定義聲音巩趁。自定義聲音的音頻編碼形式可以是以下幾種:
- Linear PCM
- MA(IMA/ADPCM)
- uLaw
- aLaw
而音頻文件應該為 .aiff
、.wav
或 .caf
文件淳附。音頻時長必須小于 30s议慰,否則系統(tǒng)會使用默認的聲音。Mac 里自帶了 afconvert 音頻格式轉換工具奴曙。如在終端中輸入如下代碼别凹,可以將 16-bit linear PCM 編碼的 Submarine.aiff
文件轉化為 IMA4 編碼的 .caf
文件:
afconvert /System/Library/Sounds/Submarine.aiff ~/Desktop/sub.caf -d ima4 -f caff -v
四、管理推送設置洽糟。由于用戶可以在設置里自由的打開或關閉 App 推送功能炉菲,在程序中,需要判斷推送功能是否可用:getNotificationSettingsWithCompletionHandler:
坤溃。
五拍霜、管理推送消息。我們可以給用戶推送消息薪介,也可以管理已經(jīng)推送或將要推送的消息祠饺。當一條消息已經(jīng)不具備時效性,那么我們就應該把它從通知欄中消除汁政。使用:removeDeliveredNotificationsWithIdentifiers:
或 removePendingNotificationsWithIdentifiers:
吠裆。
<a id="3"></a>本地消息推送實現(xiàn)
下面的代碼是實現(xiàn)了一個負責推送消息的對象,它包含了請求推送和創(chuàng)建推送消息的方法烂完。
import UIKit
import UserNotifications
internal class LocalNotificationManager: NSObject {
static let shared = LocalNotificationManager()
private let notificationCenter = UNUserNotificationCenter.current()
private override init(){
super.init()
}
//用于請求推送權限
internal func requestAuthorization(){
notificationCenter.requestAuthorization(options: [.alert, .sound]){ (granted, error) in
if(granted&&error == nil){
}else{
}
}
}
//用于創(chuàng)建推送消息(創(chuàng)建的消息將在調用函數(shù)后十秒發(fā)出)
internal func createNewNotification(){
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: "Alarm", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: "WakeUp", arguments: nil)
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)
let request = UNNotificationRequest(identifier: "MyNotification", content: content, trigger: trigger)
notificationCenter.add(request){(error) in
if let _ = error {
assertionFailure()
}
}
}
}
有了上面管理消息推送的對象,實現(xiàn)簡單的本地消息推送只需要以下兩步:
一诵棵、在 AppDelegate.swift 里的 application:willFinishLaunchingWithOptions:
調用 requestAuthorization
請求授權:
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
LocalNotificationManager.shared.requestAuthorization()
return true
}
二抠蚣、在要推送消息的地方調用:
LocalNotificationManager.shared.createNewNotification()
這樣就能收到推送的消息。
當 App 在后臺運行時履澳,消息會以橫幅的形式出現(xiàn)嘶窄。
當 App 在前臺運行時,消息會直接傳遞給 App距贷,默認狀態(tài)下不出現(xiàn)橫幅柄冲。想在前臺運行時也出現(xiàn)橫幅,可以實現(xiàn) UNUserNotificationCenterDelegate 代理方法忠蝗,在 completionHandler 里添加需要的推送形式:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(UNNotificationPresentationOptions.alert)
}
歡迎訪問我的Github:LinShiwei (Lin Shiwei) · GitHub
有任何疑問的話现横,歡迎在下方評論區(qū)討論。