首页 > ios > 走过、路过、痛过 —记那些年编码的坑

走过、路过、痛过 —记那些年编码的坑

  来聊两个故事(其实是两个事故)。

故事1

  发生在项目紧急上线前,我接手了离职同事的代码,buglist里面的烫手山芋。
  bug描述:子页面的新增插入到本页面的全部和最新的Tab下面,如果tab下面没有数据,就不插入。
  开始分析:发现下面的枚举定义

typedef NS_ENUM(NSUInteger, XXXXType) {
    XXXXTypeAll,
    XXXXTypeNew, //最新
    XXXXTypeEss, //精华
};

  还有一个array数组里面包含三个可变数组,分别作为三个Tab(顺序为全部、精华、最新)的数据源。
  我就在子页面的回调函数里面 分别写了获取array[XXXXTypeNew]和array[XXXXTypeAll]然后插入进去,但是诡异的地方发生了,最新的tab下面一直没有数据。虽然我从网络上面获取的有数据,在页面上面也显示的最新也有数据,但是为什么插入不进去?
  花了很长的时间各种排查,最后发现通过array[XXXXTypeNew]是精华的数据,最新的数据是通过array[XXXXTypeEss]获取的。一本正经的枚举变量、一本正经的注释,竟然来一个声东击西!
  填完这个千疮百孔的模块之后,我画了一个佛来镇着,有图为证:
  img_1856

故事2

  我在线上的crash日志平台收集到了这样子的crash,

Thread 0 Crashed:
0 libsystem_platform.dylib 0x3bcc3ce6 0x3bcc0000 + 15590
1 libobjc.A.dylib 0x3b6a476f 0x3b699000 + 46959
2 libobjc.A.dylib 0x3b69cfeb 0x3b699000 + 16363
3 libobjc.A.dylib 0x3b69cdb9 0x3b699000 + 15801
4 libobjc.A.dylib 0x3b6acb0b 0x3b699000 + 80651
5 我们的代码 0x001f9b51 -[我们的算法类A .cxx_destruct] (源码:33)

  很明显就是A类的dealloc除了问题,为了解决这个Bug,就review一下前同事留下的代码,忽然发现类声明里面有这样子的代码,全局搜索一下_xxx64s之类的代码没有找到,仔仔细细的看了一遍逻辑发现没有地方用到,联系上下文页没有关联的注释说明这是干啥的。我猜是他写的测试代码,写XXXDebug也是胡乱一写,忘了包含进去。

NSMutableArray *_xxx64s;
NSMutableArray *_xxx128s;
NSMutableArray *_xxx256s;
NSMutableArray *_xxx512s;
#if XXXDebug
NSString *_xxx64Desc;
NSString *_xxx128Desc;
NSString *_xxx256Desc;
NSString *_xxx512Desc;
#endif

  我的解决方案就是,把XXXDebug向上挪了挪,把_xxx64s几个变量包含起来。真机测试,没有问题。提交。QA在debug模式测试,没有问题。后来release模式下测试,也没有发现问题。于是就提交了,而且苹果也审核过了。
  关键时刻来了:用户更新之后我们的crash频繁的集中在A类,WTK,难道是上线前没有吃苹果的缘故吗?赶紧吃着苹果review A类的代码,看了很大一会儿,发现了猫腻:

- (void)各种网状的调用函数{
  int xxxLevel = 128;
#if XXXDebug
  xxxLevel = 64;
#endif
  for (; xxxLevel <= 512; xxxLevel *= 2) {
    NSString *iVarName = [NSString stringWithFormat:@"_xxx%@s",@(xxxLevel)];
    NSMutableArray *xxxRates = [self valueForKey:iVarName];
    ... 下面有很长
  }
  ... 下面还有很长
}

  我是把问题代码定位到这儿,粘出来了,看一眼就明白,当时几百行的算法类里面那叫找的辛苦哇。
  最后的解决办法就是用jspatch修复了。虽然没有影响多少用户,crash率也没有触发设定的阈值,但是心里面总是有种吃苍蝇的感觉。。。

在日常的项目开发中得克服两种心理

  1.懒惰。第一件事已经无从考证,我感觉最大的可能就是后来又改需求了,然后tab显示的顺序换了,但是枚举定义和注释呢,也懒得换了,反正自己知道这里变了。以后别人接手代码是别人的事了。。。
  2.虚荣,为了让自己看上去像个大神,就取变量必用valueForKey+字符串拼接,调方法必用NSSelectorFromString+字符串拼接,objc_setAssociatedObject当万能胶用,method_exchangeImplementations满项目飞。让人一看,不明觉厉,也只能不明觉厉了。。。

最后的话

  在编码过程中一定得记着大道至简,也许要痛过才能真真正正的明白。

  1. 还没有评论
评论提交中, 请稍候...

留言


可以使用的标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Trackbacks & Pingbacks ( 0 )
  1. 还没有 trackbacks