UILabel在iOS8下的Color Blended Layers

      现在App的页面越来越复杂,性能优化成为了开发当中非常重要的一环,并且对性能的追求越来越极致,本文将主要讲述如何解决UILabel在显示中文时,像素混合的问题,由于内容不多,所以就不作目录了,费话不多说,马上开始。

首先补充一些基础的知识点(以下知识点,均在像素对齐的情形下),我们知道GPU是图形硬件,主要的工作是混合纹理并算出像素的RGB值,这是一个非常复杂的计算过程,计算的过程越复杂,所需要消耗的时间就越长,GPU的使用率就越高,这并不是一个好的现像,而我们需要做的是减少GPU的计算量。

一个页面可以只有一个视图,也可以有很多视图,每个视图都会对应着一个的底图层,页面上的所有图层构成了一个图层树(模型树),这个图层树便是我们在屏幕上能看到的一切的来源,我们可以假设一个图层(CALayer)就是一个纹理(Texture),接下来,我会用图层来替代纹理。如果当前我们拥有一个和屏幕大小一致的单一图层,那么屏幕上的每一个像素相当于图层中的一个像素,这个时候,我们在这个图层上放置一个完全不透明的图层,那么GPU将会把上面的图层合成到下面的图层当中,由于上面的是一个完全不透明的图层,所以上面的图层会部份遮盖掉下面的图层,而在遮盖掉的矩形区域内,GPU会直接使用上面图层的像素来显示。如果我们最底的图层上放置的是一个有透明度的图层,那么在这个矩形区域里,GPU需要混合上下两个图层来计算出在屏幕上显示出来的像素的RGB值。若在同一个区域内,存在着多个有透明度的图层,那么GPU需要更多的计算才能得出最终像素的RGB值。而我们要做的就是避免像素混合,尽可能地为视图设置背景色,且设置opaque为YES,这会大大减少GPU的计算。

本文的主角是UILabel,UILabel会将字符串与背景色绘制成位图,并且显示出来,请看下图。

接下来看一下像素混合的情况(可以通过模拟器的Debug中Color Blended Layers或Instruments中Core Animation的Color Blended Layers打开)。

 

都是绿色,表示没有出现像素混合的情况,这时我们把label的背景设为透明。

上下两个视图变成了红色,出现了像素混合的情况,表示在这两个红色的区域内,GPU需要做像素混合的计算,这无疑是增加了GPU的工作,所以在任何情况下,我们都应该设置UILabel的背景色为不透明。

刚刚用来做测试的系统版本为iOS7,那么现在我们来看看iOS8的情况。

看上去跟iOS7的效果一样,现在我们来看一下像素混合的情况。

文本区域是绿色,表示没有像素混合,但显示的是英文,接下来我们试着显示中文并看看像素混合的情况。

虽然设置了背景色,但在iOS8上用UILabel显示中文却出现了像素混合的情况,这是为什么呢?我们来看看UILabel在iOS8前后的变化,在iOS8以前,UILabel使用的是CALayer作为底图层,而在iOS8开始,UILabel的底图层变成了_UILabelLayer,绘制文本也有所改变,就像上图所视(在iOS8刚发布的时候,我一度怀疑Apple歧视中文)。

那怎么解决呢?首先我们来观察一下上图,从图中我们可以看到在背景色的四周多了一圈透明的边,而这一圈透明的边明显超出了图层的矩形区域,既然发现这了一点,那么解决方案就很明了了。

设置图层的masksToBounds为YES时,图层将会沿着Bounds进行裁剪,我们来看一下修改后的效果。

label变回了绿色,表示像素混合问题已解决。

Tips:可以的话,要求美工在切图的时候,一定不要切出那些留有透明区域的图片,不然在你显示图片的时候,同样会出现像素混合问题。

本文旨在解决UILabel在iOS8及以后的系统版本中显示中文像素混合的问题,其它的性能优化,像离屏渲染,像素对齐等,网上已有大量的技术文,本文再提及也是大同小异。如果文中有说错的,还望指出,第一次写技术文,表述能力有限。

下期预告:由于现在App的页面越来越复杂,有些页面需要比较长的时间来加载,下一篇技术文将会讲述,在Push页面时的性能优化。

1 2 收藏 评论

可能感兴趣的话题



直接登录
跳到底部
返回顶部