iOS在接收Server端或者Local端的推送訊息時,我們得用上不同的方法來獲取推送訊息。
向服務器註冊推送通知
可以在開啟App會調用的函數中寫上註冊推送訊息的方法(iOS8以後參數有變,所以做了系統版本的判斷)
1 2 3 4 5 6 7 8 9 10 11 |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0){ //如果iOS系統版本為8.0以上 [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]]; [[UIApplication sharedApplication] registerForRemoteNotifications]; }else{ //如果iOS系統版本低於8.0 [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)]; } } |
註冊失敗時會調用的方法:
1 2 3 |
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { //處理錯誤 } |
推送訊息的接收狀態
首先我們要知道,當收到服務端、本地的推送訊息時,會分別調用兩個不同的方法:
1 2 3 4 5 6 7 8 9 |
//Server的推送訊息 -(void)application:(UIApplication *)app didReceiveRemoteNotification:(NSDictionary *)userInfo{ //處理訊息 } //本地的推送訊息 - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{ //處理訊息 } |
獲取狀態的方法就是Server端的app.applicationState和Local端的application.applicationState.
點進去applicationState我們會看到三種狀態,App正在被使用的時候、被掛起的時候、在後台運行的時候。
1 2 3 4 5 |
typedef NS_ENUM(NSInteger, UIApplicationState) { UIApplicationStateActive, UIApplicationStateInactive, UIApplicationStateBackground } NS_ENUM_AVAILABLE_IOS(4_0); |
一開始我資料查到這裡就開始使用推送功能了,但經過測試我發現有比較特別的情況。
App開著的時候沒有跳出推送消息的橫幅(banner)
查了資料,發現iOS6以後就改成這樣了,這樣修改的理由應該是覺得,如果兩個人在對聊的時候還一直跳出banner,這樣會讓用戶不舒服,而其實我們可以通過推送的訊息來判斷是不是需要跳出提示,而跳出提示的這個功能是需要我們自己來完成的。
App未開啟或者被系統Kill掉時收不到推送訊息
收不到推送訊息是指前面提到的Remote/Local推送訊息接收方法都沒有被調用,但是橫幅還是有出現,只是點了橫幅進去以後,我寫好的方法都沒有被調用到(比如收到有人關注我的訊息,打開App時應該直接跳出關注列表的View)。
我一開始以為這種情況就是UIApplicationStateInactive,但實際操作下來,我的方法都沒有被調用。
原來還有第三種接收訊息的情況:
當app沒有打開的狀態下,系統會正常跳出提示你有推送訊息的banner,當用戶點了banner進入App時會調用的是:
1 |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions |
所以我們需要從launchOptions這個參數中判斷是不是有推送訊息。
1 2 3 4 5 |
//當App沒有運行或者被kill掉的時候,推送會調用這個 NSDictionary *pushDict = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if (pushDict) { [self application:application didReceiveRemoteNotification:pushDict]; } |
我這裏判斷UIApplicationLaunchOptionsRemoteNotificationKey存在時,就直接把參數傳給接收remote推送訊息的方法了。
尚未解決的問題
如果App未開啟過,在收到推送訊息時,用戶不是通過推送訊息打開App而是直接點了App,我發現前面提到的方法都沒辦法獲取訊息。
在StackOverFlow上看到有個人的回答是沒辦法的….=_=
看上面的留言似乎只有iOS系統會這樣,Android就有對應的處理方法。
所以我在想,用戶如果這樣操作,而系統就不幫你的話,Server端就得保存用戶是不是已經有讀消息的資料了?
推送功能參考資料: