引言:iOS開發(fā),推送可以說是必須的傻粘,但是之前對(duì)于推送總是概念模糊每窖,最近借公司項(xiàng)目需求,深入了解了一下弦悉≈系洌“對(duì)于知識(shí)要懷有一顆敬畏的心!”稽莉,這是我iOS啟蒙老師說的話瀑志,想想真的是這樣,深感自己認(rèn)知的太淺薄劈猪!
App推送著實(shí)是很重要的一環(huán)昧甘,例如電商類的App,推送成就了其盈利的拼圖战得。
推送分為:遠(yuǎn)程推送和本地推送
遠(yuǎn)程推送:遠(yuǎn)程推送涉及較多充边,例如App運(yùn)行加載后會(huì)向蘋果的APNs服務(wù)器注冊(cè),獲得Token信息等等常侦,本文后面會(huì)介紹痛黎。
本地推送:本地推送較為簡(jiǎn)單,后續(xù)文章會(huì)介紹刮吧,本文只簡(jiǎn)單談?wù)勥h(yuǎn)程推送湖饱。
一、概要
- 注冊(cè)
- 分析接收推送消息后的調(diào)用方法
- App運(yùn)行于前臺(tái)(Active)
- App運(yùn)行于后臺(tái)(Background)
- App未運(yùn)行
二杀捻、步驟細(xì)節(jié)
注冊(cè)
推送的注冊(cè)在iOS8中API變更井厌,具體如下。相信大家都已經(jīng)了解致讥,在這里就不在贅述仅仆!這里只貼出代碼。
//設(shè)置推送
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
[[UIApplication sharedApplication] registerUserNotificationSettings:
[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}else {
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeBadge| UIRemoteNotificationTypeSound];
}
需要注意的是:settingsForTypes中的類型對(duì)應(yīng)的就是原推送各個(gè)類型垢袱,但是名稱有所變化墓拜,其中Sound為推送提示聲音,badge為applicationIconBadgeNumber请契,Alert為推送提示的文字等咳榜。
注冊(cè)成功與否
在iOS開發(fā)中,App的全局代理方法內(nèi)有2個(gè)代理方法是注冊(cè)遠(yuǎn)程推送是否成功的回調(diào)方法爽锥。
注冊(cè)成功:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
//此方法返回?cái)?shù)據(jù) NSData 內(nèi)包含此設(shè)備的Token涌韩,也就是說注冊(cè)成功了。
//在此實(shí)現(xiàn)將Token信息傳遞給你的后臺(tái)服務(wù)的代碼
}
注冊(cè)失斅纫摹:
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(@"推送注冊(cè)失敗:%@",error);
}
這里簡(jiǎn)要介紹下推送的流程臣樱,以便了解上述回調(diào)方法為什么要將Token信息傳遞給你的后端。
通俗的講:
首先腮考,App運(yùn)行并向Apple服務(wù)器注冊(cè)遠(yuǎn)程推送服務(wù)雇毫,也就是大家常聊起的APNs(APNs 是 Apple Push Notification service 的簡(jiǎn)稱),成功APNs會(huì)返回當(dāng)前設(shè)備的Token信息踩蔚,其次棚放,App內(nèi)部的邏輯就是將此Token信息,傳遞給你的后端服務(wù)寂纪,后端服務(wù)獲得此Token信息后就可以和APNs服務(wù)器“交互”了席吴,然后后端服務(wù)將要推送的某條信息,帶著Token信息推到APNs服務(wù)器捞蛋,APNs服務(wù)器拿到Token信息后孝冒,就知道要將推送消息推送到那臺(tái)設(shè)備上。
以上就是遠(yuǎn)程推送服務(wù)的大致流程(通俗理解)拟杉。詳細(xì)流程請(qǐng)參考 iOS程序犭袁 大神的文章庄涡。這是現(xiàn)階段最新的APNs介紹篇章,出自大神之手搬设,值得研讀哦穴店!_
至此,注冊(cè)成功后拿穴,就可以實(shí)現(xiàn)遠(yuǎn)程推送服務(wù)了
分析接收遠(yuǎn)程推送調(diào)用的方法
- App運(yùn)行于前臺(tái)(Active)
當(dāng)App在前臺(tái)運(yùn)行時(shí)泣洞,接收到遠(yuǎn)程通知的時(shí)候,并沒有任何的提示默色,比如聲音球凰,通知欄的提示。但是這時(shí)會(huì)調(diào)用App的代理方法(后續(xù)統(tǒng)一叫推送回調(diào)方法):
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
//實(shí)現(xiàn)你接收到遠(yuǎn)程推送的消息處理代碼腿宰;
}
- App運(yùn)行于后臺(tái)(Background)
當(dāng)App運(yùn)行與后臺(tái)的時(shí)候分為兩種情況:- 點(diǎn)擊通知欄進(jìn)入App:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
//實(shí)現(xiàn)你接收到遠(yuǎn)程推送的消息處理代碼呕诉;
}
* 點(diǎn)擊App圖標(biāo)進(jìn)入App:
`無動(dòng)作--不會(huì)調(diào)用任何推送相關(guān)回調(diào)方法`
- App未運(yùn)行
當(dāng)App未運(yùn)行的時(shí)候分為兩種情況:- 點(diǎn)擊通知欄進(jìn)入App:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions{
//判斷l(xiāng)aunchOptions字典內(nèi)是否含有推送的鍵值對(duì) Key:@“UIApplicationLaunchOptionsRemoteNotificationKey”
if ([launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"]) {
//實(shí)現(xiàn)你接收遠(yuǎn)程推送消息的消息處理代碼;
}
}
* 點(diǎn)擊App圖標(biāo)進(jìn)入App:
`無動(dòng)作 --會(huì)調(diào)用上面的didFinishLaunchingWithOptions方法吃度,但是這時(shí)launchOptions對(duì)應(yīng)的鍵值對(duì)為空甩挫,所以也不會(huì)進(jìn)入if判斷內(nèi)。`
對(duì)于App層出不窮椿每、變幻莫測(cè)的需求伊者,顯然以上可以處理遠(yuǎn)程推送的方法遠(yuǎn)遠(yuǎn)無法滿足需求!
iOS7更新推送API间护,推出了推送喚醒功能删壮,下面我們簡(jiǎn)要介紹一下推送喚醒。簡(jiǎn)單的說兑牡,就是接收到推送時(shí)央碟,系統(tǒng)將喚醒在后臺(tái)的應(yīng)用程序,并回調(diào)App代理的方法均函,執(zhí)行一些必要的代碼亿虽,例如請(qǐng)求數(shù)據(jù)、更新UI等苞也,減少用戶解鎖進(jìn)入應(yīng)用洛勉,等待數(shù)據(jù)加載的過程。詳情請(qǐng)參閱"喵神"Blog, 多多研讀喵神的Blog如迟,會(huì)使你收益頗豐收毫!
推送喚醒
如何實(shí)現(xiàn)推送喚醒呢攻走?首先是針對(duì)Xcode的,下面針對(duì)是否開啟推送喚醒進(jìn)行Xcode相應(yīng)設(shè)置此再,配置info.plist文件昔搂,如圖所示,勾選箭頭所指選項(xiàng):
[Xcode配置]
其次输拇,需要在payload中加入content-available摘符,并設(shè)置為1。
aps {
alert = "something";
badge = 0;//后端返回
content-available = 1;
sound = default;
}
當(dāng)然payload參數(shù)也可以自定義策吠,例如:場(chǎng)景為多個(gè)平臺(tái)可以給App推送信息逛裤,這時(shí)就需要一個(gè)Type判斷是那個(gè)平臺(tái)推送的消息,分別顯示等等猴抹。
然后在AppDelegate.m文件中實(shí)現(xiàn)如下方法:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler{
//實(shí)現(xiàn)處理推送消息的邏輯代碼
}
推送喚醒調(diào)用代理方法分析
- App運(yùn)行于前臺(tái)(Active)
以下分析基于推送喚醒設(shè)置成功基礎(chǔ)上带族。
當(dāng)App運(yùn)行在前臺(tái),接收到推送信息時(shí)蟀给,會(huì)調(diào)用:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler{
//實(shí)現(xiàn)處理推送消息的邏輯代碼;
}
如果沒有實(shí)現(xiàn)上述方法炉菲,則會(huì)調(diào)用:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
//實(shí)現(xiàn)處理推送消息的邏輯代碼;
}
但是在實(shí)際測(cè)試過程中,即使后端未輸出content-available = 1;結(jié)果同上坤溃,實(shí)現(xiàn)- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
(后續(xù)統(tǒng)一叫推送喚醒回調(diào)方法)方法也會(huì)調(diào)用拍霜。此問題有待后續(xù)追蹤,如有了解的煩請(qǐng)告知薪介!再此謝過祠饺!
- App運(yùn)行于后臺(tái)(Background)
當(dāng)App運(yùn)行于后臺(tái),同時(shí)接收到推送消息時(shí)汁政,推送喚醒功能就是在此時(shí)大顯神威滴O(∩_∩)O~道偷!會(huì)直接調(diào)用:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler{
//實(shí)現(xiàn)處理推送消息的邏輯代碼;
}
經(jīng)過測(cè)試,如果未實(shí)現(xiàn)上述方法记劈,則會(huì)在接收到推送的時(shí)候直接調(diào)用:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
//實(shí)現(xiàn)處理推送消息的邏輯代碼;
}
當(dāng)App運(yùn)行于后臺(tái)的時(shí)候分為兩種情況:
- 點(diǎn)擊通知欄進(jìn)入App:
測(cè)試結(jié)果為:點(diǎn)擊通知欄進(jìn)入App勺鸦,調(diào)用方法同上,也就是當(dāng)App運(yùn)行在后臺(tái)時(shí)目木,接收到推送消息時(shí)换途,直接調(diào)用回調(diào)方法,點(diǎn)擊通知欄進(jìn)入App時(shí)再次調(diào)用刽射,相當(dāng)于調(diào)用了2次回調(diào)方法军拟!想要實(shí)現(xiàn)的同學(xué),需要判斷一下誓禁,是否需要重復(fù)調(diào)用懈息! - 點(diǎn)擊App圖標(biāo)進(jìn)入App:
點(diǎn)擊App圖標(biāo)進(jìn)入App,無任何動(dòng)作摹恰,不調(diào)用任何推送相關(guān)回調(diào)方法辫继,但是在接收到推送消息的時(shí)候已經(jīng)直接調(diào)用了回調(diào)方法怒见,此過程只調(diào)用了1次回調(diào)方法罷了
經(jīng)過測(cè)試,后端未輸出content-available = 1;不會(huì)在App運(yùn)行于后臺(tái)時(shí)直接調(diào)用回調(diào)方法姑宽,但是在點(diǎn)擊通知欄進(jìn)入App時(shí)遣耍,如果實(shí)現(xiàn)了推送喚醒回調(diào)方法,則會(huì)調(diào)用推送喚醒回調(diào)方法低千,未實(shí)現(xiàn),則會(huì)調(diào)用推送回調(diào)方法馏颂。
- App未運(yùn)行
當(dāng)App未運(yùn)行時(shí)示血,即使推送喚醒也是無能為力了,因?yàn)橥扑蛦拘阎皇窃贏pp運(yùn)行在后臺(tái)的時(shí)候才有效果救拉。 - 點(diǎn)擊通知欄進(jìn)入App:
如果實(shí)現(xiàn)了推送喚醒回調(diào)方法則調(diào)用难审,未實(shí)現(xiàn)則在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions;
方法中利用字典鍵值對(duì)判斷亿絮,文章開始介紹過告喊,這就不再贅述了。
注意:不會(huì)調(diào)用推送回調(diào)方法派昧!
實(shí)際測(cè)試黔姜,即使后端未輸出content-available = 1;調(diào)用結(jié)果同上 - 點(diǎn)擊App圖標(biāo)進(jìn)入App:
點(diǎn)擊App圖標(biāo)進(jìn)入App,無任何動(dòng)作蒂萎,不調(diào)用任何推送相關(guān)回調(diào)方法秆吵。即使調(diào)用- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions;方法五慈,但是此時(shí)launchOptions字典中相應(yīng)的鍵值對(duì)值為空纳寂,所以無法處理相應(yīng)需求
。
到此泻拦,遠(yuǎn)程推送的所有回調(diào)方法的調(diào)用場(chǎng)景全部羅列完成毙芜,若有遺漏、錯(cuò)誤争拐,非常歡迎指出腋粥,煩請(qǐng)動(dòng)動(dòng)您的手指,反饋一下架曹,文章中我提到的未能明確的問題灯抛,如有了解的煩請(qǐng)告知,再次拜謝音瓷!