iOS App如何清除badge并保留通知中心的消息

Jason Yu
4 min readMar 18, 2018

--

似乎听起来这是一件很小的事,为什么要写一篇文章呢?一开始我们也觉得简单,但是最后这件事仍然是超出了我们的预期范围,因此值得稍微整理一下解决的整个过程。

清Badge?没那么容易

对于一个app,如果在home screen上的badge一直消不掉,是一个比较烦人的事。因此一般来说,app需要在未读消息都处理完的时候,通过代码把badge清零(通过本地设置badge或者远程推送badge)。

不过这样一来会有一个副作用:一旦app的badge被设置为0,系统通知中心里先前的推送都会被清空,这是一个系统隐藏的逻辑。我们的问题就是:如何在badge清零的同时,保留通知中心的推送?

一般思路

通常来说对于这类业务逻辑并不复杂,同时跟系统API紧密相关的需求,我们会尝试通过以下几个步骤来解决:

  1. 查看文档(我们发现applicationBadge和远程推送都可以设置badge,但是无法解决通知中心被清空的问题)
  2. 上Google和Stackoverflow搜索(遇到这个问题的不多,也许这是一个比较窄的case,大多数app并不关心)
  3. 尝试一些文档上没有提到的办法(这里就需要警觉了,因为RoI正在快速降低,即使猜出一个可用的办法,以后很可能还会变)记得前几年也遇到了,当时有人说把badge设置为-1可以解决,尝试了一下却不行。现在又试了一下采用Local notification的方式,仍然不行。

一般尝试到了这里,再投入更多的时间钻牛角尖往往是不明智的,省下时间来做其他的事会更有效率。我们会跟pm说no,尝试在需求上做出妥协。在与pm争论的同时,我们发现了另一个app做到了。(如果没有这件事,很可能也就没有后来的结论)

没办法,那我们干脆多花点时间,把问题一次性搞清楚,顺带给大家贡献一些成果,作为低RoI的弥补吧。

已知条件

  1. iOS9直接设置applicationBadgeCount为-1没有作用
  2. 通过push设置badge为-1没有作用
  3. 本地通知也可以设置badge
  4. 无论远程还是本地,设置为badge为0一定会清空通知中心
  5. 从iOS10开始,因为新出了UserNotification框架,本地推送的api发生了变化,老的接口deprecated(但可能仍然能用)。因此我们要同时测试iOS9、10、11三个大版本
  6. app对于推送的响应在前后台有可能不同
  7. 需要同时测试使用老的本地通知API、设置badge为-1、新的本地通知API

测试结果

“完美”表示效果与预期相符合,我们很高兴

最令人意外的是,我们之所以觉得设置badge为-1没有作用,是因为stackoverflow上说的和我们去年的测试结果确实没用——没想到到了iOS11又可以用了。那样来说,其实只有中间的iOS9和10是不行的,让人有一种“修好的bug又坏了”的感觉。这成为了iOS11上唯一能帮助我们达到目标的办法。

思考过程比结果更有价值

对于这类充满暗坑的需求,从产品的角度是很难看到的。一旦遇到了,一般工程师存在三种态度:

  1. 勤勤恳恳的工程师全部接受产品的需求,但是可能一个很小的问题需要花上整整两天时间
  2. 强硬的工程师遇到就选择拒绝,那可能会跟产品吵一架,并且需要花时间另辟蹊径
  3. 选择先评估再做取舍。如果pm一再坚持己见(这里指的并不是全部问题都持固执态度的pm,而是理性的pm),那就从一方面说明RoI中的R可能是足够的,可以适当再追加投入。争论也是评估过程的一部分。

因此,除了想把这个测试结果分享给大家,还希望分享整个思考过程(相比结果而言是更重要的):对于工程师来说,应该不断评估产品需求和开发投入之间的平衡,并把信息传递到pm达成一致。不要怕跟pm争论,适度的争论并不是完全没有意义的,相反却可以达到效率的最大化。

--

--