虽然今天是周末,但是还是要学习的不是。写这篇博客的目的呢是记录一下自己在上次项目迭代中踩的坑,不过这个坑已经填上了。虽然坑不大,但是踩上去肯定能崴脚。其实还是那句话,在没人给你指路的情况下,踩的坑多了,慢慢的就成长了。为了填今天要讲的这个坑,午觉都没睡呢。当然今天博客的内容并不高深,而且出现的几率还是蛮大的,所以喽就记录一下。也许你已经踩过,或者你已经将此坑填上,但是今天是我踩了一脚呢,没办法,还是记录一下吧。
解决历程用一个字描述就是:“删”。
一、描述这个“坑”
首先呢,我们先来看一下这个Bug的出现场景。A页面Push到B页面时,在iOS9以下的系统上就会在A页面上卡顿一段时间,然后在Push到B页面。当然A页面和B页面的东西还是挺多的。下这么一描述,下方就贴出两张应用的截图吧,应用已经上线,大家可以支持一下呢,在博客中使用App中的两张截图应该并无大碍,想必公司也是会允许的呢, 当然项目的代码是肯定不会往博客上贴的呢。
下方截图就是两个出现Bug的页面,当然,这两个部分都是我在该项目的此次需求中负责的部分了。点击“工作室”页面的“工作室信息”按钮就会Push到工作室信息的页面。在点击按钮时此刻Bug就出现了,而且只有这两个页面跳转时才会卡顿。并在iOS9以下的系统中前两次进入到“工作室信息”页面时都会卡顿,而第三次就没有这个问题了,真是事不过三呢。
A页面是Swift纯代码写的,当然,使用的是SnapKit布的局。而B页面是Objective-C写的,并且用Storyboard做的。在iOS8或者iOS7上从A push到B页面就卡,而且只有在前两次进入的时候卡,再进的话就很顺畅。这到底是为什么呢?所以喽,就开始排查Bug的过程了。
二、找“坑”
Bug出现了,现象就是“卡顿”。意识到自己已经踩在坑上了,不过踩得坑在哪儿,踩得什么坑还得排查呢。下方就是定位的整个过程。
1、缩小“坑”的范围
在"A"页面中有6个UICollectionView的Cell,点击每个Cell都会跳转到相应的页面。跳转的这些页面有Swift写的,也有OC的,有纯代码的, 也有Storyboard实现的。可是唯独只有在进入B页面的时候卡顿。所以喽,应该是B页面相关的东西出了问题。然后我们就把目标转向B页面相关的ViewController和Storyboard上的VC。
于是乎,给B页面的ViewController的viewDidLoad方法添加了一个断点,观察卡顿时是否执行了。运行了一下,点击按钮跳转发生卡顿时发现下方的断点并没有执行。也就是说,在发生卡顿时B页面的视图并未加载完毕,那就是卡顿应该发生在视图加载完成前。
接着上面的结果接着排查,为了确定是B视图加载时发生的卡顿,于是乎就写了下方的这段代码来测试是否是loadView时发生的卡顿。果然呢,点击A页面相关Cell时,打印了一个“前”的Log,然后发生卡顿。卡顿后打印了一个“后”,紧接着进入和B页面。这样一来我们就明确知道,B视图在LoadView时发生了卡顿,而B页面的视图是通过Storyboard来加载的,所以卡顿的原因就在于B页面的Storyboard中控件的实现。
2、进一步找“坑”
经过上一步,我们把iOS8+上卡顿的bug定位在了B页面的Storyboard的具体实现上。下面这个页面是使用的Static TableView来做的,每一行是一个Cell,把整个TableView给删掉,再运行就不卡顿了。于是乎把TableView上一个个静态的Cell依次的删掉,每删一个Cell就运行依次。结果把这个“简介”这个Cell删掉后就不卡了。于是乎我们就把问题定位到了“简介”这个Cell上。
把页面上的状态恢复到初始状态,然后把“个人简介”这个TextView给删了,发现就不卡了。而加上个人简介这个TextView还是会卡顿。于是乎就把问题定位到了TextView上了。那是不是该TextView的约束加的有问题呢,于是乎又把TextView上的约束给删了,不过卡顿的问题还是存在的,那肯定不是该控件的约束问题了。那肯定就是这个TextView控件本身设置的问题。
经过上述所有步骤,最终我们将该卡顿的bug定位在了B页面中个人简介的UITextView控件的加载上。
三、填“坑”
经过上面的步骤,我们找到了“坑”的位置所在。接下来得填坑不是,然后我又仔细的检查了一遍这个TextView的所有配置项,实在是看不出什么问题。然后我就把这个UITextView给删了,然后又随便拖拽了一个,发现就没有卡顿这个问题了。这么神奇呢,然后我又对比了一下刚拖拽的这个UITextView,和我之前的TextView最大的区别就在于这个新的TextView的默认文字是英文的,而之前是中文的。
冥冥之中就感觉到这是问题所在,于是怀疑到“是不是当Storyboard中的TextView的默认值是中文的时后,视图加载渲染时非常耗时呢?”。这还得靠实验来说话,于是乎,把之前的“个人简介”改成了English,然后运行,结果卡顿的问题好了!当填上这个坑的时候我的心情是激动的,虽然填坑的手段极其简单,但是填坑的姿势还是重要的。其实找“坑”的过程,比填坑的过程要有意思的多呢。
四、此次踩坑总结
在博客的最后还是要总结一下的。在iOS7.0+, iOS8.0+上如果你VC布局是用Storyboard来实现的,并且在你的VC上有UITextView这个空间,并且你又在Storyboard上给这个UITextView设置了“中文”默认值的话,那么在前两次该VC加载视图时都会卡顿。应该是在加载视图是渲染这个TextView中的“中文”默认值比较耗时。解决方法是“把这个中文默认值在Storyboard中去掉,然后在ViewDidLoad方法中添加相应的默认值”。
为了再次验证该问题,我还特地写了个小的Demo。Demo比较简单,就是两个VC, 一个VC push出另一个VC。在目标VC中有一个TextView, 而这个TextView的默认值是“中文”字符。在这种情况下,iOS8和iOS7的系统上在PUSH时就会卡顿,在iOS9上就没有问题。然后把TextView的“中文”默认值改成英文,或者去掉就解决了这个问题。
上面的所有内容就是这个“踩坑”、“找坑”和“填坑”的过程。其实寻找Bug这个过程还是蛮有意思的,虽然没睡午觉,但是也不觉得困呢。OK,今天的博客就先到这。