1. 使用不透明视图。
         不透明的视图可以极大地提高渲染的速度。因此如非必要,可以将table cell及其子视图的opaque属性设为YES(默认值)。
    其中的特例包括背景色,它的alpha值应该为1(例如不要使用clearColor);图像的alpha值也应该为1,或者在画图时设为不透明。
  2. 不要重复创建不必要的table cell。
         前面说了,UITableView只需要一屏幕的UITableViewCell对象即可。因此在cell不可见时,可以将其缓存起来,而在需要时继续使用它即可。
    而UITableView也提供了这种机制,只需要简单地设置一个identifier即可:

static NSString *CellIdentifier = @"xxx";

UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {

cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

}

值得一提的是,cell被重用时,它内部绘制的内容并不会被自动清除,因此你可能需要调用setNeedsDisplayInRect:或setNeedsDisplay方法。此外,在添加table cell的时候,如果不需要动画效果,最好不要使用insertRowsAtIndexPaths:withRowAnimation:方法,而是直接调用reloadData方法。因为前者会对所有indexPaths调用tableView:cellForRowAtIndexPath:方法,即便该cell并不需要显示(不知道是不是bug),这就可能创建大量多余的cell。勘误:只是在模拟器上测试如此,真机调试时没有这种bug。

3.减少视图的数目。

UITableViewCell包含了textLabel、detailTextLabel和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透明,或者有圆角、变形等效果,就会影响到绘制速度了。解决办法可参见后面的预渲染图像。

4.不要做多余的绘制工作。

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

5.预渲染图像。

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

6.不要阻塞主线程。

做到前几点后,你的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 *visibleIndexPathin indexPaths) {

if (indexPath == visibleIndexPath) {

MyTableViewCell *cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];

cell.image = image;

[cell setNeedsDisplayInRect:imageRect];

break;

}

}

iOS-UITableView性能优化的更多相关文章

  1. iOS程序性能优化

    iOS程序性能优化 一.初级 使用ARC进行内存管理 在iOS5发布的ARC,它解决了最常见的内存泄露问题.但是值得注意的是,ARC并不能避免所有的内存泄露.使用ARC之后,工程中可能还会有内存泄露, ...

  2. iOS 程序性能优化

    前言 转载自:http://www.samirchen.com/ios-performance-optimization/ 程序性能优化不应该是一件放在功能完成之后的事,对性能的概念应该从我们一开始写 ...

  3. 【iOS Instrument性能优化集】

    iOS Instrument性能优化集 1.UIImage缓存取舍 在项目代码中看到大量使用如下代码: UIImage使用 在Main Thread中发现不同动画场景中Image IO 开销和耗时所占 ...

  4. [深入浅出Cocoa]iOS程序性能优化

    本文转载至 http://blog.csdn.net/kesalin/article/details/8762032 [深入浅出Cocoa]iOS程序性能优化 罗朝辉 (http://blog.csd ...

  5. 【原/转】UITableview性能优化总结

    UITableView作为ios中使用最频繁的控件之一,其性能优化也是常常要面对的,尤其是当数据量偏大并且设备性能不足时.本文旨在总结tableview的几个性能优化tips,并且随着认识的深入,本文 ...

  6. UITableView性能优化

    关于UITableView的性能优化,网络上也有一些总结.在这里就介绍下我们项目中遇到的问题以及对应的解决方法.相信我们遇到的问题也有一定的普适性,能够作为其他问题的优化方案. Instruments ...

  7. UITableView性能优化及手工绘制UITableViewCell

    提高表视图的性能 UITableView作为应用中最常用的视图,它的性能优化问题几乎是经常提及.下面对在非网络访问情况下的表视图性能优化进行了主要的几点说明: 1.自定义类或XIB文件时 在系统提供的 ...

  8. iOS页面性能优化

    前言 在软件开发领域里经常能听到这样一句话,“过早的优化是万恶之源”,不要过早优化或者过度优化.我认为在编码过程中时刻注意性能影响是有必要的,但凡事都有个度,不能为了性能耽误了开发进度.在时间紧急的情 ...

  9. iOS app性能优化的那些事

     iPhone上面的应用一直都是以流畅的操作体验而著称,但是由于之前开发人员把注意力更多的放在开发功能上面,比较少去考虑性能的问题,可能这其中涉及到objective-c,c++跟lua,优化起来相对 ...

  10. iOS App 性能优化总结

    今天简单总结一些clientapp 优化的方案和方向. 我相信开发一个app大部分团队都能够完毕,可是性能久不一样啦,和我们都写一个冒泡算法一样,我相信每一个人写的冒泡算法都不一样,这些区别就带来了性 ...

随机推荐

  1. 为 Node.js 开发者准备的 8 本免费在线电子书(转)

    ode.js 是一套用来编写高性能网络服务器的JavaScript工具包,一系列的变化由此开始.比较独特的是,Node.js会假设你是在POSIX环境下运行它 Linux 或 Mac OS X.如果你 ...

  2. ThoughtWorks微服务架构交流心得

      ThoughtWorks微服务架构交流心得: (1)<人月神话>中谈到软件开发没有银弹,根源在于软件所解决的领域问题本身固有的复杂性,微服务正是从领域问题角度上进行服务拆分,来降低软件 ...

  3. 静态工具类中使用注解注入service

    转载:http://blog.csdn.net/p793049488/article/details/37819121 一般需要在一个工具类中使用@Autowired 注解注入一个service.但是 ...

  4. 有关C#中使用if else和try catch的问题及效率问题

    本来if esle 是流程控制 try catch是异常处理,本身其实是没有可比性的,但是开发过程中有的人很容易混用,而且两者有的时候效果似乎一样,所以我还是用了个简单的测试来简单的比较下. 不多说, ...

  5. node.js 对接公众平台

    http://www.tfan.org/wp-content/uploads/使用-Nodejs-和-MongoDB-开发高性能微信公众平台应用.pdf

  6. Storm实时流处理Hello World

    近来在看Storm的相关资料,以下总结一下配置过程和Hello World例子. Storm是分布式的实时计算系统.详细文档可参考Storm网站,也可以参阅<Getting started wi ...

  7. 胡扯两句——CDQ分治

    之前听大神讲过CDQ分治大概是个什么东西,但是一直还没有真正去搞过.今天稍微看了一下,写点自己的理解. 首先CDQ分治有两个条件. 条件1:可以分成两个独立互不影响的问题(这里的"独立&qu ...

  8. redis sort

    redis sort命令用法 1.命令描述返回或保存给定列表.集合.有序集合key中经过排序的元素.排序默认以数字作为对象,值被解释为双精度浮点数,然后进行比较. 2.一般sort用法最简单的sort ...

  9. [Js]无缝滚动

    效果: 1.默认缓慢往左滚动 2.放到左箭头上还是向左滚动,放到右箭头上向右滚动 3.放到图片上停止滚动,移出继续滚动 思路: 1.计算图片列表ul的宽度 2.开启定时器,使其向左边距不断增大,造成向 ...

  10. HTTP(socket)下载遇到valgrind提示的错误: Conditional jump or move depends on uninitialised value(s)

    我写了个http下载函数,下载txt.jpg都正常,就是下载php有问题:valgrind会报错Conditional jump or move depends on uninitialised va ...