在2016年2月过年期间,我们的快行app收集的线上crash突然飙升,其中一个数组越界的问题,我们很百思不得其解,起初我并不看好队友写iOS的一些习惯,但是后来觉得可能对方的编程思想导致他会有的代码风格,面对出现的很多问题,其实我看了代码也百思不得其解,只能说如果是我做,我不会那么去设计这样的iOS结构,也就不会出现这样的问题,但是作为一名百度的程序猿这样的想法是远远不够,不能理清深处的原理,错误。不能让对方信服就不太合格,自己也没有提升技术,于是我掰开他的代码,开始协作同伴一起探索真理。
线上crash崩溃地址指示在tableview 的代理内
按照原理,我们请求回来的数据是不会出现数组越界的,但是是为什么呢,就算此处做了防护,还是不知道为什么会crash,而且无法复现,跑几万次的代码,偶尔出现的2到3次的crash,后来搬出了大神深度解析;大灰灰的博客 http://www.jianshu.com/p/db19b17a88f6
查阅代码确实有很多处的dataSource直接被替换,直接被改变的地方,因为我们的程序员把城际专线,汽车票和拼车三处订单列表均实现在同一个viewController,并且tableView的代理都赋给了dataSource,通过数据源来控制,在数据源内实现代理和cell的布局,反正我重来没有这样实现过。当刷新控件在转菊花的同时cell会往下滑动,有一个cell会滚出屏幕,菊花还在转的同时 dataSource此时已经改变,菊花停止时cell往上滚动会重新绘制,此时tableVIew还没有来得及relodate刷新,菊花停止转动,cell向上移动,cell去向之前的dataSource去拿数据却已经拿不到了,因为此时的dataSource已经改变,恰好数据源比之前的数据源上两个数据,代理去读去读不到,tableView就炸掉了 。因此此种跑了上万次的才会出现几次crash的问题得到了解决
再看看写的错误代码
修改方法:把reloadData 位置放置到endRefreshing上面彻底解决问题的办法:先让tableview刷新reloadData,然后再延时0.1秒endRefresh
// 主线程延迟执行:
double delayInSeconds = 0.1f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// 延时endRefresh
});
网友评论