1. 程式人生 > >[iOS]推送相關兩點

[iOS]推送相關兩點

討論一下最近遇到的兩個問題:

1. 推送接收

2.點選推送開啟APP時資料的處理

理想情況是:

  1. app處於活躍狀態,有推送到來,在應用內部應當彈出我們自己生成的提示。
  2. app處於非活躍狀態,有推送到來,彈出系統生成的提示,點選提示會進入app並且顯示相關內容。

推送接收

考慮第一種情況,我們需要拿到資料,才能生成相應提示。與此相關的有兩個方法:

方法1.-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo

方法2.-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

這兩個方法看起來比較眼熟,區別在於哪裡呢?第二個方法是iOS7之後才出現的,與之相關的是 “iOS 7 Background Remote Notification”這種型別的通知,它允許應用收到通知後在後臺(background)狀態下執行一段程式碼,可用於從伺服器獲取內容更新。功能使用場景:(多媒體)聊天,Email更新,基於通知的訂閱內容同步等功能,提升了終端使用者的體驗。

如果你用到了這個型別的通知,需要在Xcode 中 Capabilities找到 Backgroud Modes,在 Remote notifications打鉤,這樣就開啟了“Background Remote Notification”,之後notification 處理函式一律切換第二個方法,我們應該在這裡拿資料。

如果你沒有使用這種型別的通知,你在兩個在這兩個方法裡二選一(Apple推薦第二個方法),如果兩個方法都實現了,會預設呼叫第二個方法。

If your delegate implements both methods, the app object calls the application:didReceiveRemoteNotification:fetchCompletionHandler: method.

點選推送開啟APP時資料的處理

當用戶點選通知進入app時,你可能想要展示關於這條通知的內容,比如推送了一條商品A的打折資訊,使用者點選通知進入應用後彈出一個Alert:“商品A打折,是否檢視?”。在第二個方法的文件裡有這樣一段話

If the user opens your app from the system-displayed alert, the system may call this method again when your app is about to enter the foreground so that you can update your user interface and display information pertaining to the notification

意思是當用戶點選通知進入app時,會 再次 呼叫這個方法(之所以用再次這個詞,是因為之前說過,如果你的應用處於後臺狀態並且收到“iOS 7 Background Remote Notification”這種通知,會呼叫這個方法)。如果你的iOS版本小於iOS7,這個方法就不能使用,你可以在啟動方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中拿到推送的資料:

NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(userInfo){
//do something
}

結論

  1. 如果不考慮小於iOS7的版本,所有的問題可以在方法
    -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
    中解決。
  2. 需要支援iOS7之前版本,不需要“iOS 7 Background Remote Notification”這種通知。

    • 不實現上面第二個方法,在第一個方法-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo中接收通知。
    • 使用者點選通知開啟app時,在方法 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions拿到通知資料。
  3. 需要支援iOS7之前版本,同時需要“iOS 7 Background Remote Notification”這種通知。

    這時比較容易出現重複處理的情況,如iOS7中點選推送進入app,在方法2-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler和啟動方法- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中都能獲得此條通知資料。

    • 在方法1.-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo和推送接收方法2.-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler中都獲得通知內容並處理(不同版本會呼叫不同方法,不會重複呼叫)。
    • 在啟動方法- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 中拿到推送的資料,判斷系統版本,如果小於iOS7,拿資料並處理,反之跳過不處理。