iOS遠程推送處理

本文主要講解iOS收到遠程消息后客戶端的一些處理方法,iOS 10開始蘋果單獨集成一套框架專門處理通知,可謂非常方便。至于如何集成推送,比較簡單,這里不做探討,本文主要是讓大家了解收到遠程消息后應(yīng)用程序若要做相應(yīng)的操作以及點擊通知需要做的操作,該如何去處理。

先帶大家大致了解一下推送的流程,大致三步:

  1. 應(yīng)用程序在蘋果推送服務(wù)器APNS上注冊deviceToken,APNS返回devicetoken給應(yīng)用程序,之后發(fā)送給自己的后臺服務(wù)器;
  2. 后臺服務(wù)器將deviceToken和要發(fā)送的消息一起打包發(fā)送給APNS;
  3. APNS將消息發(fā)送給deviceToken中保存的指定設(shè)備中的指定APP
APNS流程圖

好了,現(xiàn)在開始講重點了。。。

首先應(yīng)用程序接收到遠程通知時可能處于三種狀態(tài):① 程序未啟動,退出狀態(tài);② 程序處于后臺,掛起狀態(tài);③ 程序處于前臺,運行狀態(tài)。

而程序啟動也可有兩種方法:①點擊通知;②點擊應(yīng)用圖標。

本文著重對點擊通知進行深入探討,至于點擊應(yīng)用圖標進入app,受制于apple,開發(fā)者并不能做什么,故忽略。

收到消息和點擊推送消息可能會調(diào)用的5個方法如下:

①- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions NS_AVAILABLE_IOS(3_0);

此方法是當應(yīng)用程序處于退出狀態(tài)后,點擊應(yīng)用圖標或者點擊通知欄啟動程序會調(diào)用,若是點擊了通知欄啟動,則推送信息userInfo會保存在launchOptions這里

if (launchOptions) {
    NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    self.userInfo = userInfo;
}

很多時候我們點擊通知欄啟動app需要跳轉(zhuǎn)到相應(yīng)的頁面(有時通知欄的消息類型不一樣,所需跳轉(zhuǎn)的頁面也不一樣),我們可以先將userInfo保存起來(self.userInfo = userInfo),待app初始化完之后,再在main控制器里的viewDidAppear里進行跳轉(zhuǎn),跳轉(zhuǎn)完之后再把userInfo清空,否則每次進入此控制器都會跳轉(zhuǎn),或者對它設(shè)置只執(zhí)行一次的操作。但是點擊通知欄除了會調(diào)用此方法,還會調(diào)用方法②(iOS 7.0)或者④(iOS 10.0),若在這個方法里做了操作還需進行另外的處理,請看下面。

② - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler NS_AVAILABLE_IOS(7_0);

此方法為iOS 7.0之后,若實現(xiàn)了此方法,則下面的方法③就會被覆蓋,不被調(diào)用。

收到通知,若處于前臺則會調(diào)用,若處于后臺并不會調(diào)用,若要想在后臺收到通知調(diào)用(app想在后臺收到通知之后做一些刷新UI的操作),則需后臺服務(wù)器配上content-available = 1這個字段,同時在Xcode里Capabilities中Background Modes里面勾選了Remote notifications為YES。點擊通知欄則一定會調(diào)用,若想點擊之后做一些跳轉(zhuǎn)頁面的操作,還需加一些判斷條件:

if (application.applicationState == UIApplicationStateActive) {

} else if (application.applicationState == UIApplicationStateInactive) {
     // 在這里進行跳轉(zhuǎn)操作

} else if (application.applicationState == UIApplicationStateBackground) {

}

為什么要加判斷?上面講了,處于前臺和后臺收到通知會調(diào)用此方法,不加判斷處于前臺和后臺的話,就會自動跳轉(zhuǎn)咯。并且還要判斷①方法中是否有保存userInfo,若有說明是啟動app同時也會調(diào)用此方法但不需在這里執(zhí)行跳轉(zhuǎn)(因為你前面做了跳轉(zhuǎn)處理了,不然要跳兩次)。

總結(jié):①app處于前臺,收到通知會調(diào)用;②app處于后臺,收到通知,若配置了以上所講則會調(diào)用,否則不調(diào)用;③點擊通知欄,無論app處于后臺、前臺、退出都會調(diào)用

③ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo NS_DEPRECATED_IOS(3_0, 10_0, "Use UserNotifications Framework's -[UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:] or -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:] for user visible notifications and -[UIApplicationDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] for silent remote notifications");

此方法,只有當app處于前臺收到或者點擊通知才會調(diào)用。若有實現(xiàn)方法②,則此方法作廢;若未實現(xiàn),點擊通知的處理與方法②一樣,就不過多贅述了。

④ - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);

此方法為iOS 10獨享的,將本地推送和遠程推送都統(tǒng)一在這個方法里。只有當app處于前臺時收到通知(本地和遠程)會調(diào)用此方法。有點需要注意,若想在前臺時收到通知不展示出來,則需在此方法中這樣處理:

 completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound);  // 不需展示
 completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert);  // 需要展示
⑤ - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler __IOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0) __TVOS_PROHIBITED;

此方法為iOS 10獨享的,將本地推送和遠程推送都統(tǒng)一在這個方法里。當app處于后臺時收到通知(本地和遠程)會調(diào)用此方法,對于遠程推送也需后臺服務(wù)器配置content-available = 1這個字段且Remote notifications為YES,否則處于后臺收到推送不調(diào)用,點擊通知則一定會調(diào)用,交互處理方法同②。

若為iOS 10,但并未實現(xiàn)④和⑤,則還是iOS 7 8 9之前一樣,調(diào)用相應(yīng)的方法。

總結(jié)(最低為iOS 7.0):

  1. app處于退出狀態(tài),所有方法都不調(diào)用,只有點擊應(yīng)用圖標才會調(diào)用方法①,點擊通知欄iOS 10 調(diào)用①和④,非iOS 10調(diào)用①和②;
  2. app處于后臺,若有content-available = 1和Remote notifications為YES,iOS 10 調(diào)用⑤,非iOS 10調(diào)用②,否則不調(diào)用;點擊通知欄又會調(diào)用一次,iOS 10 調(diào)用⑤,非iOS 10調(diào)用②;
  3. app處于前臺,iOS 10調(diào)用④,非iOS 10調(diào)用②;點擊通知欄又會調(diào)用一次,iOS 10 調(diào)用④,非iOS 10調(diào)用②;

以上為后臺遠程推送,需要后臺必須配置字段badge、alert、sound,若有靜默推送的需求,則必須加上content-available = 1,且必須去掉字段badge、alert、sound

以上是工作中總結(jié)出來的,希望能幫助到大家,如有不正確之出,歡迎指出。

另外,本人在處理推送時遇到了一個比較大的坑,在推送時,APNS會返回說一個無效的token,導(dǎo)致推送失敗,配合后臺花了大半天才解決,大致原因如下:

  1. 在推送時,遇到失效的TOKEN導(dǎo)致消息推送失敗。查閱很多資料,都說一旦遇到一個失效的TOKEN,同一個隊列中,從失效的TOKEN往后的消息都無法推送
  2. 即便通過APNS提供的方法,定時獲取失效TOKEN進行刪除,但是由于有一定的延遲,從失效TOKEN開始,往后一定時間內(nèi)推送的消息,還是無法正常的推送到用戶手機上
  3. 如果一旦遇到失效TOKEN,蘋果推送服務(wù)器,是否會主動斷開連接。
  4. 有人提供的方法是:每發(fā)送一定數(shù)量的消息,就檢查一下是否有失效TOKEN,如果有就刪除失效TOKEN,從新獲取新的連接。就像上面說的,因為有一定的延遲(延遲多長時間還不清楚),即便通過這種方式,好像也沒辦法保證大批量消息丟失啊。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 極光推送: 1.JPush當前版本是1.8.2,其SDK的開發(fā)除了正常的功能完善和擴展外也緊隨蘋果官方的步伐,SD...
    Isspace閱讀 6,874評論 10 16
  • 前言 本文是一篇轉(zhuǎn)載文章,在這一篇實用的文章里,你可以按照上面的步驟實現(xiàn)不借助第三方和服務(wù)器端,自己給自己的設(shè)備發(fā)...
    進無盡閱讀 1,814評論 6 6
  • 版權(quán)聲明 本文翻譯自:raywenderlich.com 原文作者: Jack Wu 譯者: JMStack 轉(zhuǎn)載...
    jmstack閱讀 7,671評論 6 30
  • 注:此文只現(xiàn)在已經(jīng)不能適配iOS10了,iOS10推送采用了新的方法,做iOS9及以下的系統(tǒng)可讀此篇文章。 最近公...
    TIME_for閱讀 33,666評論 85 322
  • 引言:iOS開發(fā),推送可以說是必須的,但是之前對于推送總是概念模糊,最近借公司項目需求,深入了解了一下?!皩τ谥R...
    ibabyblue閱讀 1,462評論 36 8

友情鏈接更多精彩內(nèi)容