原文:10 Actionable Performance Tips To Speed Up Your Table View
翻译: 10个加速Table Views开发的Tips
在我们开始之前,我准备从今年开始多听取一个意见。请花一些时间通过这篇简短的调查给我们一些反馈。这将会帮助我来帮助你。
如果你曾经跟collectionview打过交道,你可能已经意识到了这篇文章的价值。如果你没有注意速度这将会是一个大问题,你的用户会让你了解的。当你的scrollview没有你设备上的其他app的速度快的时候你将会很快意识到。Table views是每一个iOS初级开发者最先使用到的,也可能很快就陷入困惑。这篇文章将会深入讲解一些也许你正在查找的问题。
龟兔问题
Table views是一种交互对象,许多app利用它展示结构化的数据。想要很好的利用它是很琐细的,这使得他们使用起来犹如曲折的冒险。设计者在设计之初不考虑性能的问题。设计者甚至可能是你自己。很快你将会做一个图片类型的app,它需要在cell上展示许多信息。开始的时候可能很快但是很快就慢的像乌龟一样。你想让你的Table views顺畅得像一片黄油。你的app的这些使用效果如果不好的话很快就会能够注意到。
加速你的Table Views
我们会通过一个实际的例子来探索这些小提示,这个例子中的Table views实现得很不好。
通常你会发现一个图片类的app会在一个imageview上做下面这些事情:
- 下载图片(主要的内容图片+用户头像图片)
- 更新时间戳
- 展示评论
- 计算动态的cell的高度
在这个例子中我们打算集中分析以上几点内容。
我建议你去克隆下来那个demo的目录(github)去体验一下一开始的时候它是多么糟糕。跳到XMCFeedTableViewCell看下它的提升并且感受一下它的性能。如果你在iphone 6+上面运行的话优化感受起来可能不那么好,意识到这点很重要。不要忘了在一台更旧的设备上体验一下。
Tip#1 学习怎么提升速度
我可以写一整篇关于Instruments的文章。在这儿我将给你一个大致的介绍因为这会很有帮助的。
如果你对于Instruments不是很有经验,我劝你周末花些时间来研究一些。当你想要测量内存与时间消耗,他们会帮你很大的忙。然而当你着手做一个app你将会在开发过程中遇到很多问题,代码会变得越来越糟,这时你可能还无暇顾及性能的问题。但是重构是潜在的。为了合适的重构你应该花费精力在分析性能上面。
所以,下面是周末探索内容:
-
打开你的项目并点击Product>Profile
-
在那儿选择Custom
-
找到添加按钮并且添加工具:Allocations,Time,Profile,Leaks
-
观察你的应用,以及他的表现。
例如,我们关心的是速度(但是内存也是一个大问题)。我们需要哪个工具呢?如果你选择Time Profile那你就对了。让我们打开它并观察下运行中的app。
下面你就能看到我们的app的概况。你所看到的就是我打开app并且尽我可能快的上下滚动tableview。这就模拟出了一个很好的“最坏情况假设”,然后我们就可以采取行动了。
这个区域就是我开始滚动app时会执行的代码,我们只想知道在这个区域的时间消耗。
现在你可以开始研究我们上面讨论的代码了。双击这些行中的任何一行(最好是最上面一行,那就是时间被消耗最多的地方)
需要指出很重要的一点,那就是Call Tree下面的选项不是为你在Instruments加载时设置的。你需要自己去设置。
Tip#2 避免阻塞主线程
在这个例子中你会看到第一个图片相关的方法在数据下载并转换成图片对象时阻塞了主线程。你要尽量避免阻塞主线程,这对于collection中的交互对象尤为重要。网络请求?保持他们在后台运行(异步的)并且缓存传回的响应。你肯定不想重复处理任何操作。想象你的cell在一段沉默时间内被绘制。你的cell应该只展示已经保存在你的设备上的数据。这会使你感觉更好的。
Tip#3 重用cells
如果你已经花了一些时间学习iOS,那么不好意思 。这条建议是给那些新接触iOS的同学的。你应该使用dequeueReusableCellWithIdentifier 这个方法去获取一个table或者collection上面的cell。如果你不是这样做的,你就浪费了一段无意义的时间和数据。
Tip#4 缓存下载的图片
这肯定是你在这里读到的最重要的一条建议了。如果你不缓存图片你将会遇到很大的问题。
如果你重用本地的图片那么请使用UIImage的方法imageNamed:。以JPG格式请求图片将会节省时间和资源。如果你是从服务端获取图片那么你就可以获取所需要的那些图片( If you’re getting your image from a server you have the luxury of sending the exact image that’s needed.)。 PNG文件在内存中会占用很大一部分空间。如果你对此感觉好奇你可以在示例中将JPG换成PNG来下载一系列的PNG图片。
使用 SDWebImage 或者 Heneke 来管理图片。在提供的示例中我就是用的 Heneke,在那之前我没有听说过它也没有听说过它的好用之处。
Tip#5 使用富文本标签代价是很昂贵的
费尽周折用富文本标签,代价太昂贵了。尽可能地避免使用这个。问问你自己是否真的需要这个。如果是的话,尽可能的做缓存。
Tip#6 cell高度计算
如果你的table有复杂的动态高度那么你需要缓存计算的高度。考虑多久计算一次(尤其是对于collection views来说),你希望这些高度都是直接可用的。
Tip#7 NsDateFormatter 的痛苦
就像富文本,如果你频繁地初始化,date formatter可以引起大量的内存消耗。比较理想的是你的web端为你提供可读的文字(比起在最后的时间计算要容易很多)。如果没有的话你可以创建一个NSDateFormatter的单例来使用。NSDateFormatter不是线程安全的,但是iOS7以及之后就不再是这样了。多谢quellish提醒我这一点。
Tip#8 透明度
如果你能避免的话你创建的对象最好是不透明的(非透明的,你不能透过它看过去)。如果你有透明的图片,系统必要要很努力地重绘这些图片。实际上你可以在模拟器中通过点击Debug>Clolor Blended Areas来看这些区域的问题。
看到红色的了么,那就意味着这些区域是透明的。当你在跟一个Collectionview打交道时这将是非常耗时。理想的,你想看到整个屏幕都是绿色的。对于你的设计来说那可能是不可行的,但是力求减少你看到的红色的数量。在示例中你可以看到label延伸到了view的尾部,可以被清除掉。
Tip#9 不要过多使用Xib(如果可以的话使用storyboard)
如果要使用xib就要小心一点。当你加载一个Xib,整个的内容会被加载到内存中(图片,隐藏的views)。但是这在storyboard中不会发生他只会实例化当前要用的东西。
有一些特殊的场景下使用xib很有意义。比如你可能会要使用一些第三方的框架而他们采用纯代码的方式来写collection的UI部分。如果你想用xib来创建一个原型cell你可以用xib来做。只是要小心不要过载。
Tip#10 使用CoreGraphics
我很少需要这个,但是当你需要的时候你可以用。使用CoreGraphics并在一个view的drawRect的方法中写你的UI代码。
挑战
谁不喜欢一个好的挑战?让我们在这儿来把它保持下来。这周花时间来做下面两件事。
学习怎么使用Instruments(time profiler, allocations)
通过测试图片缓存(关掉,打开,观察)来检查学习Instruments使用的情况。
https://github.com/mcgraw/dojo-table-performance
问题和回答
还没有问题!请留下评论或者发送给david@xmcgraw.com。
Takeaway
在iOS中界面的交互很重要。这是不可妥协的。如果你不花时间在稳固你的应用在设备上的体验,那么人们可能就会离你很远。当我回顾应用中的内容时应用应该是顺畅的。
轮到你了
对于提升性能你的首要建议是什么?我很乐意听取你的建议。请您有空的时候在下面分享。