Swift中的NSAttributedString draw(in:rect)性能不好吗?

时间:2018-12-01 07:44:38

标签: ios swift

我有一个UIView,它可能同时在屏幕上包含400-500多个字符串。并且此UIView是可滚动的。首要决定是将UICollectionView与自定义布局一起使用。当UIcollectionView中的项目同时在屏幕上的数量不超过30-50时,此功能非常有用。如果我挤压UIView(通过捏合手势)并且同时在屏幕上显示100-150多个项目,则尝试滚动时会出现滞后(帧速率降低并绘制1帧所花费的时间超过20-50)毫秒)。

好的。然后,我决定绝对手动绘制UIView。对于绘制形状,我使用CGContext(即使同时绘制1000-2000个形状,效果也很好)。但是,当我尝试使用NSAttributedString draw(in:rect)绘制许多字符串(100-300)时,滚动时会产生非常糟糕的性能。

绘制50个字符串(帧率可以,绘制时接近16ms) enter image description here

绘制150个字符串(帧率很差,绘制时接近30ms) enter image description here

绘制300个字符串(帧速率很差,绘制时接近60ms) enter image description here

所以,问题是为什么Swift中的NSAttributedString draw(in:rect)性能不佳?即使我同时向View中添加300 UILabel并尝试滚动其帧速率也是可以的(仅此而已)每帧17ms)。 UILabel如何在屏幕重绘时在内部绘制文本以实现高性能?

1 个答案:

答案 0 :(得分:1)

在大多数情况下,自己绘制图纸并不能改善性能。

UILabel快速,因为它必须只绘制一次字符串。然后,它将绘制的字符串的位图图像保留在其后备存储中。此后将在每个帧中重复使用。所有视图位图的合成也将通过GPU完成。

如果您自己绘制图形,则很有可能无法从缓存的后备存储中受益。正如您所注意到的,必须重绘整个视图很慢。可以通过仅重绘实际更改的部分(使用setNeedsDisplay(rect))来进行改进,但是在缩放时通常是不可能的。手动绘制速度很慢,因为用于此目的的所有Core Graphics API都在CPU而非GPU上运行。

您使用具有自定义布局的集合视图的方法应该能够很好地解决这一问题。编写性能良好的集合视图布局并不容易,但是可以做到。也许您应该使用仪器进行调查,然后问另一个问题。