在說Push Notification的響應之前,先來討論下iOS應用程序的狀態(tài),回調(diào)方法以及狀態(tài)切換
- 應用程序的狀態(tài)
| 狀態(tài) | 說明 | 描述 |
|---|---|---|
| Not Running | 未運行 | 程序沒啟動 |
| Inactive | 未激活 | 程序在前臺運行,不過沒有接收到事件。在沒有事件處理情況下程序通常停留在這個狀態(tài) |
| Active | 激活 | 程序在前臺運行而且接收到了事件。這也是前臺的一個正常的模式 |
| Backgroud | 后臺 | 程序在后臺而且能執(zhí)行代碼,大多數(shù)程序進入這個狀態(tài)后會在在這個狀態(tài)上停留一會。時間到之后會進入掛起狀態(tài)(Suspended)。有的程序經(jīng)過特殊的請求后可以長期處于Backgroud狀態(tài) |
| Suspended | 掛起 | 程序在后臺不能執(zhí)行代碼。系統(tǒng)會自動把程序變成這個狀態(tài)而且不會發(fā)出通知。當掛起時,程序還是停留在內(nèi)存中的,當系統(tǒng)內(nèi)存低時,系統(tǒng)就把掛起的程序清除掉,為前臺程序提供更多的內(nèi)存。 |
-
回調(diào)方法
- application:didFinishLaunchingWithOptions:
- 本地通知:UIApplicationDidFinishLaunchingNotification
- 觸發(fā)時機:程序啟動并進行初始化的時候后。
- 適宜操作:這個階段應該進行根視圖的創(chuàng)建。 - applicationDidBecomeActive:
- 本地通知:UIApplicationDidBecomeActiveNotification
- 觸發(fā)時機:程序進入前臺并處于活動狀態(tài)時調(diào)用。
- 適宜操作:這個階段應該恢復UI狀態(tài)(例如游戲狀態(tài))。 - applicationWillResignActive:
- 本地通知:UIApplicationWillResignActiveNotification
- 觸發(fā)時機:從活動狀態(tài)進入非活動狀態(tài)。
- 適宜操作:這個階段應該保存UI狀態(tài)(例如游戲狀態(tài))。 - applicationDidEnterBackground:
- 本地通知:UIApplicationDidEnterBackgroundNotification
- 觸發(fā)時機:程序進入后臺時調(diào)用。
- 適宜操作:這個階段應該保存用戶數(shù)據(jù),釋放一些資源(例如釋放數(shù)據(jù)庫資源)。 - applicationWillEnterForeground:
- 本地通知:UIApplicationWillEnterForegroundNotification
- 觸發(fā)時機:程序進入前臺,但是還沒有處于活動狀態(tài)時調(diào)用。
- 適宜操作:這個階段應該恢復用戶數(shù)據(jù)。 - applicationWillTerminate:
- 本地通知:UIApplicationWillTerminateNotification
- 觸發(fā)時機:程序被殺死時調(diào)用。
- 適宜操作:這個階段應該進行釋放一些資源和保存用戶數(shù)據(jù)。
- application:didFinishLaunchingWithOptions:
-
狀態(tài)切換
- 啟動程序
Not running =》Inactive =》Active- willFinishLaunchingWithOptions
- didFinishLaunchingWithOptions
- applicationDidBecomeActive
- 按下home鍵
Active =》Inactive =》Background =》(Suspended =》Not Running)- applicationWillResignActive
- applicationDidEnterBackground
- applicationWillTerminate:
- 雙擊home鍵,再打開程序
- applicationWillEnterForeground
- applicationDidBecomeActive
- 啟動程序
言歸正傳,來說說Push Notification的響應。首先說iOS 10 之前?;卣{(diào)函數(shù)有兩個,分別是
- application:didReceiveRemoteNotification:
- application:didReceiveRemoteNotification:fetchCompletionHandler:
這兩個函數(shù)有什么區(qū)別呢?
簡單來說,iOS7以上,你只需要實現(xiàn)第二個函數(shù)即可。因為如果你兩個函數(shù)都實現(xiàn)的化,程序只會調(diào)用第二個。(相信現(xiàn)在也沒有什么iOS不支持iOS7了吧。)
具體的請參考蘋果文檔
https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623117-application
https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application
| APP狀態(tài) | 消息推送 | 用戶操作 | 是否觸發(fā) |
|---|---|---|---|
| Not Running | 收到推送消息提示 | 點擊消息 | YES |
| Not Running | 收到推送消息提示 | 點擊APP | NO |
| Background | 收到推送消息提示 | 點擊消息 | YES |
| Background | 收到推送消息提示 | 點擊APP | NO |
| Active | 無推送消息提示 | 無 | YES |
那么什么情況下application: didReceiveRemoteNotification: fetchCompletionHandler: 會被觸發(fā)?
| APP狀態(tài) | 消息推送 | 用戶操作 | 是否觸發(fā) |
|---|---|---|---|
| Not Running | 收到推送消息提示 | 點擊消息 | YES |
| Not Running | 收到推送消息提示 | 點擊APP | NO |
| Background | 收到推送消息提示 | 點擊消息 | YES |
| Background | 收到推送消息提示 | 點擊APP | NO |
| Active | 無推送消息提示 | 無 | YES |
結(jié)論:如果應用不在激活狀態(tài),點擊APP激活應用是不會觸發(fā)application:didReceiveRemoteNotification:fetchCompletionHandler函數(shù)的,只有點擊推送過來的消息,才會觸發(fā)函數(shù)調(diào)用。
此外,在iOS7之后,不需要再考慮在應用未啟動狀態(tài)下,接到推送消息,在application: didFinishLaunchingWithOptions:中獲取推送信息了。因為application:didReceiveRemoteNotification:fetchCompletionHandler在這種情況下會被調(diào)用。如果還繼續(xù)在application: didFinishLaunchingWithOptions:中做推送處理,那么就會出現(xiàn)重復。
再看iOS10的情況,iOS10提供了兩個delegate函數(shù),分別對應應用處于激活狀態(tài)和非激活狀態(tài)
- userNotificationCenter:willPresentNotification:withCompletionHandler:
- userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
| APP狀態(tài) | 消息推送 | 用戶操作 | 是否觸發(fā) |
|---|---|---|---|
| Not Running | 收到推送消息提示 | 點擊消息 | 觸發(fā) didReceiveNotificationResponse |
| Not Running | 收到推送消息提示 | 點擊APP | NO |
| Background | 收到推送消息提示 | 點擊消息 | 觸發(fā) didReceiveNotificationResponse |
| Background | 收到推送消息提示 | 點擊APP | NO |
| Active | 可自定義 | 無 | 觸發(fā)willPresentNotification |
觸發(fā)willPresentNotification可自定義是否彈出消息提示,此時,若點擊消息提示,則會調(diào)用didReceiveNotificationResponse。
綜上,正確處理badge更新的好時機
-
程序不在前臺
- 我們可以在applicationDidBecomeActive函數(shù)中從服務器獲取各個badge的信息,并進行UI更新。
- application:didReceiveRemoteNotification:fetchCompletionHandler 和application:didReceiveRemoteNotification:fetchCompletionHandler函數(shù)內(nèi)僅處理對應頁面的跳轉(zhuǎn)。
程序在前臺
application:didReceiveRemoteNotification:fetchCompletionHandler 和userNotificationCenter:willPresentNotification:withCompletionHandler函數(shù)內(nèi)從服務器獲取各個badge的信息,并進行UI更新。但不需要做對應頁面的跳轉(zhuǎn)。不希望打斷用戶當前的行為。