近期發現一個蛋疼的問題,ios裏清程序角標的時候會把通知欄的推送消息也清了。試驗了好久得到了一些結論,記錄下結果。
推送分爲遠程推送和本地推送。分開來記錄。
在遠程推送的協議中,有一個badge字段,這個字段是用來設置程序角標值的。當app處於非運行狀態或者在後臺時,收到遠程推送,app並不會運行任何代碼,一切事務都是由系統處理(iOS 7推出的靜默推送是特例)。此時收到推送,系統會根據推送消息的aps裏的內容執行操作,包括:"sound"-提示音、"alert"-通知欄顯示的推送內容、"badge"-程序角標值、"content-available"-靜默推送標誌。sound、alert和content-available就不提了,單說badge。分爲下面幾種情況。
1.收到推送前程序角標爲零,收到的推送消息badge爲0。此時角標一直處於爲零的狀態(爲零時不顯示角標)。
2.收到推送前程序角標爲零,收到的推送消息badge大於0。此時角標從不顯示變爲badge的值。
3.收到推送前程序角標不爲零,收到的推送消息badge爲0。此時角標從顯示變爲不顯示,且清空所有通知欄的消息,包括新收到的推送消息。
4.收到推送前程序角標不爲零,收到的推送消息badge大於0。此時角標值更新。
本地推送通過UILocalNotification對象發送,UILocalNotification有一個applicationIconBadgeNumber屬性,作用與遠程推送的badge字段類似,針對上而的四種情況,結果與遠程推送相同。但需要注意一點:當applicationIconBadgeNumber設爲零(也是默認值)時,意味着不改變程序角標,而不是將程序角標置零。順帶說一下UILocalNotification的cancelLocalNotification:和cancelAllLocalNotification方法,這兩個方法是清除那些在日程表中尚未推送的本地推送消息,而不是清除通知欄內的推送消息。通知欄內的消息完全由系統控制,程序無法獲得。只有當用戶點擊了通知欄的消息,系統調起app的didReceiveRemoteNotification或者didReceiveLocalNotification方法會將點擊的推送內容傳遞給這兩個方法,app才能獲得這些數據。
另外,UIApplication也有一個applicationIconBadgeNumber的屬性,該屬性就是代指程序角標的。可以在代碼中直接更改該屬性的值,其效果與遠程推送的四種情況類似。強調一點,當程序角標爲非零時,將UIApplication的applicationIconBadgeNumber屬性設爲零,會清空通知欄。
綜合上面的結論,一旦將程序的角標從非零置爲零,就會清空通知欄的所有通知。如果想清除角標但不清空通知欄,有如下方法。
1.發送一條遠程推送,推送內容只有badge,並將badge的值設爲負數。此時程序角標會消失但是通知欄的推送消息不清除。
2.同樣的方法,發送一條本地推送。
注:不能通過直接將UIApplication的applicationIconBadgeNumber設爲負數的方法解決問題,實驗證明,這種做法一樣會清空通知欄。
總結一句:蛋疼的推送!!