iOS 10:本地消息推送及實現(xiàn)

文章結(jié)構(gòu):

<a id="1"></a>前言

這階段在學(xué)習(xí)有關(guān) iOS 10 消息推送的內(nèi)容,通過查閱資料并親身實踐,對消息推送有了一定的理解。因此寫這篇文章,希望對剛接觸 iOS 消息推送的開發(fā)者有幫助。

Apple 應(yīng)用的消息推送分為本地消息推送(Local Notification)和遠程消息推送(Remote Notification)。當(dāng)有新的消息時,可以通過本地或遠程推送告知用戶,即使 App 并未運行。

  • 本地消息推送不需要聯(lián)網(wǎng),由系統(tǒng)統(tǒng)一管理 App 推送的消息,App 只需與系統(tǒng)交互即可。本地消息推送適用于 iOS、tvOS 和 watchOS。
  • 遠程消息推送需要連接網(wǎng)絡(luò),通過 App 或者后臺服務(wù)器與 Apple Push Notification(APN) 通信,再由 APN 將消息推送到終端上。遠程消息推送除了支持 iOS、tvOS 和 watchOS,還支持 macOS。

本文將大體介紹消息推送的相關(guān)內(nèi)容,并實現(xiàn)基本的本地消息推送。想直接看如何實現(xiàn)本地消息推送,請看“本地消息推送實現(xiàn)”部分。

<a id="2"></a>iOS 消息推送的基礎(chǔ)知識

<a id="21"></a>推送方式

盡管消息推送方式分為本地和遠程,但是他們展現(xiàn)給用戶的方式是一樣的,因為它們默認(rèn)使用的是系統(tǒng)提供的外觀。主要的推送方式有:

  • 通知、橫幅
  • 應(yīng)用圖標(biāo)標(biāo)記
  • 帶有聲音的通知、橫幅或標(biāo)記

<a id="22"></a>管理消息推送

App must be configured at launch time to support local and remote notification.

首先,我們需要在 applicationDidFinishLaunching: 之前聲明支持消息推送的方式。如果想在 App 運行后某個時間再進行聲明的話,在此之前要避免推送消息。因為在聲明支持消息推送之前,發(fā)送任何消息都是無效的。

當(dāng)配置了消息推送的方式后,需要請求授權(quán):requestAuthorizationWithOptions:completionHandler:,第一次調(diào)用該方法時,系統(tǒng)會提示用戶 App 需要推送消息,等待用戶確認(rèn)。系統(tǒng)自動保存用戶的授權(quán)結(jié)果,當(dāng)以后調(diào)用該方法時,就不會在出現(xiàn)提示了。

獲得推送消息權(quán)限后,就需要考慮以下幾個問題:

一、設(shè)定 Category。當(dāng) App 推送的消息很多,需要進行分類時,就需要設(shè)定 Category。

let generalCategory = UNNotificationCategory(identifier: "GENERAL",actions: [],intentIdentifiers: [],options: .customDismissAction)
 // Register the category.
let center = UNUserNotificationCenter.current()
center.setNotificationCategories([generalCategory])

設(shè)定消息的 Category 后,就可以添加自定義的行為(action),這樣用戶就可以在不打開 App 的情況下,對消息進行簡單的操作。如果不為消息分配 Category,那么消息就會以默認(rèn)的形式推送,不帶有任何附加的行為。

二、為 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

而音頻文件應(yīng)該為 .aiff.wav.caf 文件。音頻時長必須小于 30s,否則系統(tǒng)會使用默認(rèn)的聲音。Mac 里自帶了 afconvert 音頻格式轉(zhuǎn)換工具。如在終端中輸入如下代碼,可以將 16-bit linear PCM 編碼的 Submarine.aiff 文件轉(zhuǎn)化為 IMA4 編碼的 .caf 文件:

afconvert /System/Library/Sounds/Submarine.aiff ~/Desktop/sub.caf -d ima4 -f caff -v

四、管理推送設(shè)置。由于用戶可以在設(shè)置里自由的打開或關(guān)閉 App 推送功能,在程序中,需要判斷推送功能是否可用:getNotificationSettingsWithCompletionHandler:

五、管理推送消息。我們可以給用戶推送消息,也可以管理已經(jīng)推送或?qū)⒁扑偷南ⅰ.?dāng)一條消息已經(jīng)不具備時效性,那么我們就應(yīng)該把它從通知欄中消除。使用:removeDeliveredNotificationsWithIdentifiers:removePendingNotificationsWithIdentifiers:

<a id="3"></a>本地消息推送實現(xiàn)

下面的代碼是實現(xiàn)了一個負(fù)責(zé)推送消息的對象,它包含了請求推送創(chuàng)建推送消息的方法。

import UIKit
import UserNotifications

internal class LocalNotificationManager: NSObject {
    static let shared = LocalNotificationManager()
    private let notificationCenter = UNUserNotificationCenter.current()
    private override init(){
        super.init()        
    }
    //用于請求推送權(quán)限
    internal func requestAuthorization(){
        notificationCenter.requestAuthorization(options: [.alert, .sound]){ (granted, error) in
            if(granted&&error == nil){
                
            }else{
                
            }
        }
    }
    //用于創(chuàng)建推送消息(創(chuàng)建的消息將在調(diào)用函數(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: 調(diào)用 requestAuthorization 請求授權(quán):

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
        LocalNotificationManager.shared.requestAuthorization()  
        return true
}

二、在要推送消息的地方調(diào)用:

LocalNotificationManager.shared.createNewNotification()

這樣就能收到推送的消息。
當(dāng) App 在后臺運行時,消息會以橫幅的形式出現(xiàn)。
當(dāng) App 在前臺運行時,消息會直接傳遞給 App,默認(rèn)狀態(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ū)討論。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內(nèi)容