在项目中写一些冗余代码

来源:互联网 发布:普通网络作家没收入 编辑:程序博客网 时间:2024/06/05 16:45

#引子

最近,扇贝单词书改版上线了,但根据Bugly的追踪日志发现:在iOS 9.x.x设备上,当用户获取单词书分类信息时,会出现莫名的闪退(专业地说是程序崩溃)。做为这一块的开发人员,自然而然要负起修复这个异常的责任!(外加深刻地自发地过失检讨)借助Xcode的断点调试功能,我开始了问题的回溯与分析。

#过程

看着这个崩溃在主函数的异常,我们都会感到很“亲切”!第一步当然是打开全局的异常断点,观察一下是否是某些代码出现数组越界、字典的值为nil之类的异常。然而,情况依旧没有什么改变,并且控制台也没有什么异常的信息打印。我便意识到这个问题可能不会很容易检查出来了,至少从表面看,从代码本身,没有发现什么问题。

于是,进行第二步,即单步调试。根据崩溃调用栈的信息,问题是进行UICollectionView的属性约束时发生的(方法是系统私有的方法),问题就被锁定到了UICollectionView的配置上面了。

它的dataSource是通过网络请求获取的,而在控制器要展示它的时候,实际上就会调用它的数据源方法。当时没有注意到这点(实际上UITableView也是如此,不然刷新数据就不应该叫做reloadData了。在学习这些需要配置数据源的UI控件,我想我们都写过硬编码,即直接写死分区数、行数、Cell的数据。而在这个过程中我们并没有手动调用reloadData之类的方法。),因为发现网络请求的回调还没进行时(会手动调用reloadData),数据源方法已经被触发了,然后程序就崩溃了!

在前辈的提醒下,结合自己之前写代码的经历,明白了这个行为是正常的。于是目光就集中在了返回行数的这个数据源方法里了,最开始以为是访问nil数组的count并让它参与计算导致的(其实,我心里一直郁闷这不应该啊!),做了一些简单的代码的填充,比如判断当前数据模型的数组是否为nil之类的,随后发现程序崩溃的异常解决了!因为当天需要发加急版本,忙于测试,问题的本质没有时间去仔细思考。在当前需要提交的周结的自我检讨里面,写出的关于这次崩溃的原因就是nil数组的访问,虽然我心里一直想这不可能啊!

到了第二天,虽然加急版本已经解决了崩溃的问题,但还是没有解决我的郁闷。然后就继续不好意思地叨扰坐在旁边的前辈,寻求帮助!他对我说了一句话:“其实,你们还是没有找出问题的本质!虽然问题已经解决了!”

接着他非常耐心地给我仔细分析了返回行数的数据源方法里可能会出现的问题。这里面的伪代码如下:

return hotCategoriesCount + (self.categories.count - 2 * hotCategoriesCount) * indexPath.section

这里的hotCategoriesCount是一个定值:6,表示单词书的热门分类。self.categories是从服务器请求的所有的分类信息,包含了热门分类。我们会有两个分区来展示它们,一个是热门,另一个是其他。所以,如果以这种编码的话,在self.categories还是nil的时候,这个方法的返回值就是 6 和 -6。

以上便是问题的所在!经过仔细的代码测试发现,并不是返回负值导致程序的崩溃,而在返回了正值之后返回负值才是问题根本之所在。可能在iOS 9.x.x中,API的设计人员觉得这和实际逻辑不符合,因为在之前的分区有了行数之后,后面的分区不可能会出现负值的情况。(估计在 iOS 10之后,改变了这一看法,因为可能会有些程序员写出这样的代码,比如说我,/(ㄒoㄒ)/~~)

#总结

这个问题发生的根本原因在于过于追求代码的简洁(其实丧失了可读性),没有使用冗余代码做防御式编程。导致我现在有种“一朝被蛇咬十年怕井绳”的感觉,在配置这种需要数据源的视图时,一定要考虑indexPath.row / section在不在数组的范围之类的。虽说代码变得有些啰嗦,但至少可以让自己更加放心,不会发生低级的崩溃问题。因为实际的使用场景可能会有各种各样的问题发生,防范于未然总不会错的。

随便吐槽一句,测试的时候一定要覆盖所有目前支持的系统版本啊,无论是developer还是QA

原创粉丝点击