怎样优化UITableView的性能

 在iOS App中,UITableView应该是使用率最高的。同一时候也是最为复杂的视图。
差点儿全部自带的应用中都能看到它的身影,可见它的重要性。

  在使用UITableView时,会常常遇到性能上的问题,普遍表如今滚动时比較卡。特别是table
cell中包括图片的情况时。
实际上仅仅要针对性地优化一下,这样的问题就不会有了。有兴趣的能够看看LazyTableImages这个官方的样例程序,尽管也要从网上下载图片并显示。但滚动时丝毫不卡。

  首先说下UITableView的原理。有兴趣的能够看看《About Table Views in iOS-Based
Applications》。
UITableView是UIScrollView的子类,因此它能够自己主动响应滚动事件(一般为上下滚动)。
它内部包括0到多个UITableViewCell对象,每一个table
cell展示各自的内容。

当新cell须要被显示时,就会调用tableView:cellForRowAtIndexPath:方法来获取或创建一个cell。而不可视时,它又会被释放。由此可见,同一时间事实上仅仅须要存在一屏幕的cell对象就可以,不须要为每一行创建一个cell。

  此外。UITableView还能够分为多个sections,每一个区段都能够有自己的head、foot和cells。而在定位一个cell时,就须要2个字段了:在哪个section,以及在这个section的第几行。这在iOS
SDK中是用NSIndexPath来表述的,UIKit为其加入了indexPathForRow:inSection:这个创建方法。
其它诸如编辑之类的就不提了。由于和本文无关。介绍完原理,接下来就開始优化吧。

使用不透明视图。
不透明的视图能够极大地提高渲染的速度。因此如非必要。能够将table
cell及其子视图的opaque属性设为YES(默认值)。
当中的特例包括背景色,它的alpha值应该为1(比如不要使用clearColor);图像的alpha值也应该为1。或者在绘图时设为不透明。

不要反复创建不必要的table
cell。
前面说了,UITableView仅仅须要一屏幕的UITableViewCell对象就可以。

因此在cell不可见时。能够将其缓存起来,而在须要时继续使用它就可以。
而UITableView也提供了这样的机制,仅仅须要简单地设置一个identifier就可以:

static NSString *CellIdentifier = @"xxx";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell ==
nil) {
    cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]
autorelease];
}
  值得一提的是,cell被重用时,它内部绘制的内容并不会被自己主动清除,因此你可能须要调用setNeedsDisplayInRect:或setNeedsDisplay方法。

  降低视图的数目。
UITableViewCell 也能够私人定制。
每一个Cell
中可包括Label、ImageView等多个子View。你还能够自己定义一些视图放在它的contentView里。这里须要指出的是。view是非常大的对象。创建它会消耗非常多内存。而且也影响渲染的效果。
假设你的table
cell包括图片,且数目较多。使用默认的UITableViewCell会非常影响性能。

奇怪的是,使用自己定义的view,而非提前定义的view,明显会快些。
当然,最佳的解决的方法还是继承UITableViewCell,并在其drawRect:中自行绘制:

- (void)drawRect:(CGRect)rect {
    if (image) {

[image drawAtPoint:imagePoint];
        self.image = nil;
    } else
{
        [placeHolder drawAtPoint:imagePoint];
    } 

[text drawInRect:textRect withFont:font
lineBreakMode:UILineBreakModeTailTruncation];
}

  只是这样一来,你会发现选中一行后,这个cell就变蓝了。当中的内容就被挡住了。最简单的方法就是将cell的selectionStyle属性设为UITableViewCellSelectionStyleNone。这样就不会被高亮了。

  此外还能够创建CALayer。将内容绘制到layer上,然后对cell的contentView.layer调用addSublayer:方法。这个样例中,layer并不会显著影响性能,但假设layer透明,或者有圆角、变形等效果,就会影响到绘制速度了。解决的方法可參见后面的预渲染图像。
不要做多余的绘制工作。

  在实现drawRect:的时候,它的rect參数就是须要绘制的区域。这个区域之外的不须要进行绘制。
比如上例中,就能够用CGRectIntersectsRect、CGRectIntersection或CGRectContainsRect推断是否须要绘制image和text。然后再调用绘制方法。

  预渲染图像。
你会发现即使做到了上述几点,当新的图像出现时,仍然会有短暂的停顿现象。解决的办法就是在bitmap
context里先将其画一遍,导出成UIImage对象,然后再绘制到屏幕。具体做法可见《利用预渲染加速iOS设备的图像显示》。
不要堵塞主线程。

  做到前几点后。你的table
view滚动时应该足够流畅了。只是你仍可能让用户感到不爽。常见的现象就是在更新数据时,整个界面卡住不动,全然不响应用户请求。

出现这样的现象的原因就是主线程运行了耗时非常长的函数或方法,在其运行完毕前。无法绘制屏幕和响应用户请求。当中最常见的就是网络请求了,它通常都须要花费数秒的时间,而你不应该让用户等待那么久。

  解决的方法就是使用多线程,让子线程去运行这些函数或方法。

这里面另一个学问,当下载线程数超过2时。会显著影响主线程的性能。因此在使用ASIHTTPRequest时,能够用一个NSOperationQueue来维护下载请求,并将其maxConcurrentOperationCount设为2。而NSURLRequest则能够配合GCD来实现,或者使用NSURLConnection的setDelegateQueue:方法。
当然,在不须要响应用户请求时。也能够添加下载线程数,以加快下载速度:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
willDecelerate:(BOOL)decelerate {
    if (!decelerate) {

queue.maxConcurrentOperationCount = 5;
    }
}

-
(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {

queue.maxConcurrentOperationCount = 5;
}

-
(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {

queue.maxConcurrentOperationCount = 2;
}

  此外,自己主动加载更新数据对用户来说也非常友好,这降低了用户等待下载的时间。比如每次加载50条信息,那就能够在滚动到倒数第10条以内时,加载很多其它信息:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (count - indexPath.row < 10 && !updating) {
        updating = YES;
        [self update];
    }
}
// update方法获取到结果后,设置updating为NO

  另一点要注意的就是当图片下载完毕后,假设cell是可见的,还须要更新图像:

NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];for (NSIndexPath *visibleIndexPath in indexPaths) {  if (indexPath == visibleIndexPath)   {   MyTableViewCell *cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];   cell.image = image;   [cell setNeedsDisplayInRect:imageRect];    break;  }}// 也可不遍历。直接与头尾相比較。看是否在中间就可以。

最后还是前面所说过的insertRowsAtIndexPaths:withRowAnimation:方法,插入新行须要在主线程运行,而一次插入非常多行的话(比如50行),会长时间堵塞主线程。而换成reloadData方法的话,瞬间就处理完了。
转载仅供參考。版权属于原作者。

时间: 2024-11-06 15:14:04

怎样优化UITableView的性能的相关文章

优化UITableView滚动性能

自定义的cell如下: 第一个:Instruments测试,iphone4 38fps-45fps,iphone3G 25fps // table with normal XIB based cells - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"CustomC

如何优化UITableView的性能

在iOS App中,UITableView应该是使用率最高的,同时也是最为复杂的视图. 几乎所有自带的应用中都能看到它的身影,可见它的重要性. 在使用UITableView时,会经常遇到性能上的问题,普遍表现在滚动时比较卡,特别是table cell中包含图片的情况时. 实际上只要针对性地优化一下,这种问题就不会有了.有兴趣的可以看看LazyTableImages这个官方的例子程序,虽然也要从网上下载图片并显示,但滚动时丝毫不卡. 首先说下UITableView的原理.有兴趣的可以看看<Abou

【UIKit】UITableView.05 性能优化

UITableView.05 性能优化: [为何要性能优化]:TableView拖屏过程中,不断有对象"消失"在屏幕上,但是这样的对象还是存在的,当拖拉过多后,导致内存严重泄漏. 解决方法:仅提供有限的对象,拖拉过程中,只是将内存地址存放的内容进行改变. [旧代码] -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITable

如何快速优化手游性能问题?从UGUI优化说起

WeTest 导读 本文作者从自身多年的Unity项目UI开发及优化的经验出发,从UGUI,CPU,GPU以及unity特有资源等几个维度,介绍了unity手游性能优化的一些方法. 在之前的文章<手游内存占用过高?如何快速定位手游内存问题>中提到,Mono内存和native内存是PSS内存主要的组成部分,mono内存更多的起到内存调用的功能,因此常常成为了开发人员优化内存的起点:而在游戏的其他的进程中,同样有很多因素影响着游戏的性能表现.本文将从UGUI的优化角度,介绍unity游戏性能优化的

Tomcat 7优化前及优化后的性能对比

Tomcat 7在我们日常开发.测试.生产环境都会使用到,但对于大部分开发人员来说,对其性能还是没有多大了解.本文就对它做一次性能测试,对比优化前后的性能区别. 一.运行环境 CPU: Intel(R) Pentium(R) [email protected]  : 内存:4G,装的是32位win7,只认出3G,没有花时间去整ramdisk之类的东西: 操作系统:win7 32位: JDK:1.7.0_55 Tomcat:7.0.53 大家不要笑,公司电脑,就给配这样的,慢的要死,悲剧! 下面所

java gc的工作原理、如何优化GC的性能、如何和GC进行有效的交互

java gc的工作原理.如何优化GC的性能.如何和GC进行有效的交互 一个优秀的Java 程序员必须了解GC 的工作原理.如何优化GC的性能.如何和GC进行有效的交互,因为有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等.只有全面提升内存的管理效 率,才能提高整个应用程序的性能. 本篇文章首先简单介绍GC的工作原理,然后再对GC的几个关键问题进行深入探讨,最后提出一些Java程序设计建议,从GC角度提高Java程序的性能. GC的基本原理     Java 的内存管理实际上就是对象的管

优化手机游戏性能,美术相关

何时选择3D(何时保留2D) 作为一个3d游戏美术,我得到的第一个关键教训就是,让所有的东西尽可能的保持低模--不要使用额外的不必要的顶点,如果你确实要让你的模型拥有精度,把它放置在贴图中.比如说,我们的建筑物都是用简单的方块创建而成,然后贴上带有质感的细节纹理. 当我们要为Vogel教授(它只在我们游戏的GUI和HUD中出现)建模时,首先尝试的是3D模型,但是最终,我们还是把它分解为像Flash中那样的多层2D平面.它运行非常流畅,看上去也更棒,事实最终的结果比用3D模型赞非常多!使用带有动画

CSS性能分析,如何优化CSS提高性能

css匹配原理 在优化css之前我们需要了解下css是怎么进行工作的,我们都知道css是由选择器,属性和属性值构成的. 我们可能会这样写上一行代码 //css .con .loulan1 p span{ display: block; } //html<div class="con">     <div class="loulan">         <p><span>文字</span></p>

Tomcat 7优化前及优化后的性能对比(转载)

一.运行环境 CPU: Intel(R) Pentium(R) [email protected]  : 内存:4G,装的是32位win7,只认出3G,没有花时间去整ramdisk之类的东西: 操作系统:win7 32位: JDK:1.7.0_55 Tomcat:7.0.53 大家不要笑,公司电脑,就给配这样的,慢的要死,悲剧! 下面所有测试都是基于1000个请求做的,且都是访问Tomcat默认的ROOT首页 二.未调优前 并发用户数从10-1000挨个测试,测试结果如下: 从上面的测试结果来看