肇鑫的技术博客

业精于勤,荒于嬉

咕唧在iPad浮屏时,有时会意外地重新加载账户头像问题的处理

咕唧在iPad浮屏时,既屏幕右侧向里滑动弹出咕唧,有时会出现全部头像闪动一下的问题。这个问题没什么规律,如果立即你把它划回去,再重新滑出来,它就又没有这个问题了。另外,我在iOS 12的时候也没有遇到过这个问题。

我认为这可能是iOS 13 beta独有的一个问题。

我尝试解决这个问题。

方案一

因为视图是UITableView,我尝试减少reloadData()的次数。仔细阅读代码,修改了几处限定条件,减少了reloadData()。并且出于调试目的,我在预期不应该发生的位置,插入fatalError()强制结束应用。

测试结果

方案一减少了重新加载表格视图的次数,但是对于解决该问题无效。测试中发现,偶尔还是会出现重新加载头像的问题,并且,应用没有崩溃,也就是说,我预期不会执行的部分,也的确没有执行。

方案二

因为问题是和头像有关,于是着重查看头像部分的代码。

cell.imageView?.image = profileImage
            
DispatchQueue.main.async {
    ProfileImageHelper.decorate(cell.imageView!, for: accountCore.type)
}

这段代码使用了异步代码,在UI队列里执行了对于UIImageView的装饰。这里必须使用的原因是cell.imageView是只读属性,不能直接替代。并且,当cell.imageView?.image = profileImage之后,如果立即装饰图片视图,图片视图的尺寸还是0,必须在下一个事件循环才能获得实际尺寸。

imageView_decoration

上图是咕唧账户头像的部分截图。照片原本是正方形,在实际显示时,被处理为圆形。并且,根据账户类型的不同,加上了颜色不同的圆圈。

我们知道,异步的代码,与同步不同,是分成两次执行的。因此,存在一种可能,既第一部分的代码执行了之后,很久,第二部分才执行。这在显示上,就会出现先显示方形的头像,然后才变成圆形和圆圈,就像看幻灯片那样。

须要将此部分的代码由异步改为同步。

此前采用异步的原因是无法立即知道图片视图的大小,改成同步,就必须修改代码,手动指定视图的大小。我们知道,这在平时其实是一种不好的行为。代码写死了,就失去了灵活性。但是这里,我们不得不把它写死。

通过调试,我们知道这里目前的大小是48.0点。(点,point,是苹果使用的相对大小的尺寸单位)。

cell.imageView?.image = profileImage
ProfileImageHelper.decorate(cell.imageView!, for: accountCore.type)

测试结果

这次的测试很成功,之后没有发现再次出现这个问题。

方案三

虽然问题解决了,但是写死代码还是不够灵活。思考了一下,虽然图片视图的尺寸不能立即知道,但是图片的尺寸是可以知道的。因此,将写死的代码,改为使用图片的尺寸。这样问题就彻底解决了。

思考

虽然这个问题很有可能是iOS 13 beta引入的,但是解决掉这个问题,还是有收获的。我们在实际编程中,应该尽量减少异步代码的使用。因为,有时,异步代码会带来意想不到的问题。