美文网首页
AsyncDisplayKit 的坑及解决过程(一)

AsyncDisplayKit 的坑及解决过程(一)

作者: FingerStyle | 来源:发表于2019-07-20 00:10 被阅读0次

先说下背景:

我们的APP是一个典型的电商APP,其中商品详情页是一个结构比较复杂的页面,从上到下有图片、标题、各种价格、优惠券、服务承诺、图文详情、推荐商品等等。整体布局采用AsyncDisplayKit来做的(其实用tableView或者collectionView也可以,性能上不会有太大差异),这里面有一个比较麻烦的问题,就是我们的数据是分了多个接口返回的,优惠券、推荐商品和运费这些是单独的接口,详情主体数据又是另一个接口。为了能让用户尽快看到主要信息,我们是同时请求多个接口,谁先返回谁先展示,展示的时候需要刷新一下页面。

最开始我们的做法是数据返回后整体刷新,也就是 reloadData,但是由于AsyncDisplayKit异步刷新的原理,会造成屏幕闪一下的感觉,用户体验相当不好。调研了一下发现有些node 可以设置一些属性避免闪动,但并不是所有node都可以设置。于是我们就想对一些次要的信息所在的cellnode进行局部刷新(也就是reloadSections),

 self.tableNode.reloadSections([indexPath.section], with: .none)

但是问题就来了,我们发现崩溃相当频繁,经常会报一个错, 就是 

"Invalid number of items in section %ld. The number of items after the update (%ld) must be equal to the number of items before the update (%ld) plus or minus the number of items inserted or deleted (%ld inserted, %ld deleted).

翻译过来就是 某个section更新后的item数量 != 更新前的item数量+/- 增删item数量

相信写过collectionView的 insertRow或者deleteRows这类方法的同学应该对这类报错不陌生了,原因就是collectionView 局部刷新的过程中发现数量不正确。以往这种问题的解决方式都是直接reloadData,但是这跟ASTableNode还有有些不同。

一开始我以为是AsyncDisplayKit的bug,因为跟几个同事交流都说AsyncDisplayKit比较容易崩溃,也就没多想,改成了全局刷新,虽然崩溃是不会发生了,但是这样一来闪动就特别频繁。设计说能不能让他不要闪那么厉害, 我说我研究看看,然后经过多次测试,我发现如果在整个页面加载之前,对优惠券(sectionA)做局部刷新就一定会崩溃。于是我对优惠券的局部刷新做了延迟处理,发现崩溃确实少了些,然后打包给测试和设计去测。但是这只是在测试环境页面不太复杂的情况下,实际在生产环境跑了几次之后,发现还是会崩溃,测试还提了个P1的bug。经过仔细研究,发现是多个cell的数据没有同步刷新导致的。 商详里面可变的cell比较多,有优惠券(sectionA)、图文详情(sectionB)、cod(sectionC)等,有些cell是数据没有返回时不展示,有些是高度不固定,一直变化(如图文详情在webview加载完成之前高度会一直变化,为了获取到他真正的高度,就必须不断reload这个cell) 而这些数据彼此间没有关系,本来应该是不需要同时刷新的,但由于asyncDisplaykit的机制问题,要求必须同时刷新,否则就会触发里面的断言。也就是说当sectionA要刷新的时候,发现整个tableNode中还有sectionB、sectionC的数据更新了,但视图的数量没有对应上的话,就会崩溃。

由于临近发版,怕做大的改动时间来不及,就还是改回去reloadData的方式,也就是全局刷新,但是自己内心里面对于这个问题还是希望有一个完美的解决方案,于是我又继续研究了一会。我发现如果 同时刷新会变的那几个cell(sectionA & sectionB & sectionC),就可以把闪动的影响降到最低,同时又不会触发崩溃,然后就按这种想法改好打了个包去试了一下。经过测试同学和自己不断的重试,也没有再次发现崩溃,这就证明了这个方法是可行的,也是目前来讲用户体验最好的解决方案。

var sections = IndexSet(arrayLiteral:                 SectionType.coupon.rawValue,SectionType.detailPic.rawValue, SectionType.detailText.rawValue)     //所有可变的cell的index集合       

self.tableNode.reloadSections(sections, with: .none)

所以说遇到问题还是要多思考,有些问题从表象上来看是系统或者框架的问题,但实际上可能是自己对于框架不够了解,多去钻研,问题总有解决的办法。

相关文章

网友评论

      本文标题:AsyncDisplayKit 的坑及解决过程(一)

      本文链接:https://www.haomeiwen.com/subject/rlgelctx.html