美文网首页
系列:iOS开发-如何快速定位bug并解决

系列:iOS开发-如何快速定位bug并解决

作者: spicyShrimp | 来源:发表于2017-09-26 10:11 被阅读710次

    系列:iOS开发-快速定位bug并解决

    本来没有打算针对这个开文的,

    昨天工作忙完,闲来无事的时候,逛逛论坛,贴吧啥的,偶然间就发现了有人发bug帖.
    http://www.jianshu.com/p/b51ead39c55d

    上面说的神乎其神呢...
    大家可以去看看.

    怀着好奇的态度,下载了源码
    干净的很,任何代码都没有
    只有sotryboard 拖拽了几个控件, 绑定了present和dismiss的事件而已,除此以外没有任何代码
    类似这样


    这里写图片描述

    于是编译运行项目
    按照他说的,确实出现了这个小而且偏的bug复现

    于是想要解决bug

    • 解决bug第一步

    首先不管理内存什么的问题,怀疑是不是vc没有释放?
    于是在vc的dealloc中添加打印

    
    -(void)dealloc{
        NSLog(@"%s",__FUNCTION__);
    }
    
    

    运行.返现没有任何问题,vc能够正常释放,但是textField确实没有被释放.排除vc引用

    • 解决bug第二步
      关闭bug描述中所说的第一个关键条件


      这里写图片描述

    编译运行,发现bug已经没有复现了,项目运行正常,vc能够释放,textField也能够释放.所以下定解决,出现bug的原因就是这个属性了.

    • 解决bug第三步
      既然关闭了该属性,就能解决bug,那么bug肯定是这个属性导致的,
      于是考虑能否使用手写的方式.于是在vc中给这些小控件命名, 且手动设置该属性


      这里写图片描述

    编译运行,bug复现,说明该属性在iOS11下确实会强引用控件,导致不能释放,

    • 解决bug第四步
      既然强引用导致的释放问题,那么调整引用时机即可, 这里能想到的是使用弱指针,或者其他弱引用打破强引用即可
      思路一,使用block来打破,这里因为UITextField没有相关的block方法,添加方法也没有什么意思,放弃
      思路二,使用UITextField的代理,因为使用过代理的开发者都知道,其实weak属性,所以其已经打破了强引用的条件,我们只需在适当的代理方法中设置即可
      于是添加代理


      这里写图片描述

    代理完毕之后,找到合适的地方写需要的代码即可


    这里写图片描述

    遍历代理方法,发现这三个方法应该都是可以使用的,于是选择第一条,在准备编辑的时候便开始设置相关属性,于一开始就设置应该是一样的效果,完全不影响之前的效果
    于是添加代码

    -(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
        if (textField == self.psdTextField) {
            textField.secureTextEntry = YES;
        } else {
            textField.secureTextEntry = NO;
        }
        return YES;
    }
    

    再次编译运行,
    bug已经不见了释放问题得到解决.

    • 解决bug第五步
      为了防止会再次出现其他莫名bug,需要设置一些通用的设置,比如界面释放结束编辑,vc释放前释放代理等
    - (IBAction)back:(id)sender {
        [self.view endEditing:YES];
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    

    所以整个bug修复的过程就是取消storyboard的secureTextEntry属性,改为手动添加,防止强引用,改为到代理里面设置,让系统自动帮我们打破强引用即可.

    bug修复demo
    https://github.com/spicyShrimp/iOS11_UITextField_Fix

    其实这是一个很简单的bug修复问题
    所以这个问题其实引出了我们作为iOS开发如何能快速定位bug的问题
    在我们开发的时候,我们会经常出现各种莫名的bug,而自己却不能够定位,找不到思路,其实对于bug定位这个是一个技巧和经验的问题

    大家都知道的方式有,打断点,逐行判断,打印log,判断是否正确输出...
    经验在丰富一点的会使用控制台来po一些属性的值...
    这些基本上每一个开发者都天天在用.

    但是并不是这些就能完全的解决bug了
    解决bug不是一味的出现bug,并且明确了bug发生的地方才能解决,很多bug是系统本事遗留导致
    比如,我上篇博文说的文件索引在XCode9中的问题导致的bug就和代码完全无关
    比如,上面提到的bug,小而偏,完全无法定位bug出现在哪一行
    比如,我昨晚帮网友解决的一个响应链关系的bug,视图层次都是正确的,但是就是没有响应事件,网友却认为是子控件本身的bug导致,却没有换个思路,想到关于图层结构,是否可以响应事件,等基本常见bug,(最终问题也是出在的这里,图层window的问题,这里不赘述了)

    所以这里我简单的总结一些解决bug的经验,分享给大家,希望大家都没有bug,

    1. 多打印log----log能够最简单直接的反应很多东西,比如属性的值,比如对象的类是否正确.....


      这里写图片描述
    2. 多添加关键断点----类似于log,我们每一个有问题的bug,大部分都是有复现路径的,我们需要逐步分析这个复现路径,就需要对每一个关键点添加断点,逐一排除即可修复


      这里写图片描述
    3. 学会使用异常断点等高级方式
      当我们无法明确某些复现路径的时候,我们可以通过异常断点来破获问题出现的地方


      这里写图片描述

      关于使用方法,大家可以自行网上学习一下,即可

    4. 学会使用po命令---- 添加断点,出现异常或者中断之后,对于没有log的信息,我们可以使用po命令来获取.


      这里写图片描述
    5. 学会使用其他工具,工具很多,这里不做介绍,比如instrument等.这些工具的掌握对于解决bug是很有帮助的


      这里写图片描述
    6. 使用crash日志---我们可以使用本地保存crash日志,也可以使用一些三方的bug收集SDK进行接入,比如bugly等,其可以在一定程度上定位到bug出错的位置,帮助我们解决
    7. 分析bug出现关键因素,对于上述还是无法定位bug的,我们需要自行分析bug出现的关键因素,不要放过任何一个细节,比如找不到某某方法,那就是要么没有引用文件,要么没有添加到项目,要么没有实现方法,要么编译器没有找到索引路径等.再比如上面的bug问题,关键点就是一个属性导致,我们在定位bug初期就应该能够想到,但是很多人却会忽略它
    8. 使用一些不同的思路去打破bug路径,这个是经验的问题,很多bug,使用普通的思路无法解决,可能是系统私有化,可能是时间拿不到,可能是其他一些因素无法控制,此时就需要经验了,如何能够改变思维,改变固有想法去绕过bug,也是需要掌握的,大家可以参考我的另一篇博客 ------( iOS11 导航栏按钮位置问题的解决 http://blog.csdn.net/spicyShrimp/article/details/77891717)
      对应很多因为系统限制的原因,无法使用正常思维解决的,我们就要另辟蹊径,至于如何做,这里只能说,熟能生巧
    9. 多积累基础知识,很多bug出现的因素并不是必然的,往往都是开发者的不严谨的逻辑造成的,所以算法的优劣,思路的清晰能够帮助我们减少很多bug,但是bug出现也不要担心,解决一次,就增长了一份记录,我们只要记录下来,下次就会自行很快的解决了,学习的路径有很多,论坛,书籍,视频,交流等..我们都不应该放过
    10. 对于每一个iOS或者Xcode的升级(其他开发工具或者开发环境也一样),如果可以,尽早的去适应和学习新的不同点,及早的思考某些API的改变会对我们的开发造成什么影响,做到提早预防

    其实,能否对bug的快速定位,也间接反映了你的能力水平
    希望大家在开发的时候永远没有bug....

    欢迎访问我的系列博客
    系列:iOS开发-前言+大纲
    http://blog.csdn.net/spicyShrimp/article/details/62218521

    相关文章

      网友评论

          本文标题:系列:iOS开发-如何快速定位bug并解决

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