我如何加快UITableView?

我有一个UITableView与200个部分中的约400个单元格,它响应用户交互(滚动,select单元格)有点迟缓。我已经确保检索单元格和标题视图的方法做到最低限度,因为它正在运行,我觉得我没有做任何不寻常的事情来让它变慢。 单元格和头文件只有一个背景图像和文本。 有没有其他人有这样的问题,你知道任何方式,使其运行速度更快一点?

编辑:我提供一个赏金,因为我很想得到一些有用的反馈。 我认为答案在于我的代码中存在问题。 相反,我正在寻找策略来重新deviseUITableView,使其运行速度更快。 我完全打开添加新的代码,我期待着听到你们不得不说的话。

在模拟器和我的设备iPhone 4上都观察到了不viewForHeaderInSection下面是viewForHeaderInSectioncellForRowAtIndexPath ,这是唯一实现的UITableViewDelegate方法。 我正在重复使用单元格和标题视图。

 - (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger) section { HaikuHeaderView* view= [m_sectionViews objectAtIndex:section]; NSMutableArray* array= [m_haikuSearch objectAtIndex:section]; Haiku* haiku= [array objectAtIndex:0]; [view.poetLabel setText:[haiku nameForDisplay]]; return view; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; cell.backgroundView= [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cell gradient2.png"]]; // (Set up a bunch of label attributes in the cell...) } NSMutableArray* array= [m_haikuSearch objectAtIndex:indexPath.section]; Haiku* haiku = [array objectAtIndex:indexPath.row]; cell.textLabel.text = [haiku.m_lines objectAtIndex:0]; return cell; } 

即使你的单元格其实很简单(背景图片和标签),也有一些事情要考虑

图像caching这是显而易见的事情 – 如果您在各处使用相同的图像,请将其加载到UIImage中并重新使用。 即使系统将自己caching,直接使用已经加载的应该也不会受到伤害。

快速计算另一个相当明显的事情 – 尽可能快地计算高度和内容。 不要做同步提取(networking调用,磁盘读取等)。

图像中Alpha通道当绘图是透明时,什么是昂贵的。 由于您的单元格背景没有任何背景,请确保您保存没有Alpha通道的图像。 这节省了大量的处理。

透明标签背景视图顶部的标签也是如此,不幸的是,它不透明可能会破坏您的单元格的外观 – 但这取决于图像。

自定义单元格通常, UITableViewCell子类化和实现drawRect:自己比构build子视图层次结构更快。 你可能会让你的图像成为所有实例使用的类variables。 在drawRect:您将在其上绘制图像和文本。

检查合成模拟器有一个工具来突出显示由于透明度渲染昂贵的部分(绿色是好的,红色是alpha混合)。 它可以在debugging菜单中find:“颜色混合层”

如果你想加快你的代码,你可以做的最好的事情就是分析它。 有两个原因:

  1. 你可以阅读一些通常会改善表格性能的东西,比如使用固定高度的单元格和重新使用单元格,这可能有助于实现这些东西(看起来你已经做了这些)。 但是当谈到加快你的代码时,你真的需要知道你的应用在哪里花费大部分时间。 可能有几种方法需要很长时间,或者是一种相对较快的方法,但是比预期的要多得多。

  2. 不可能知道,为了加快速度,你所做的改变是否真的有所作为,除非你有一些数字来衡量。 如果你能够certificate你的代码在一个例程中花费了80%的时间,而你将代码降低到了35%,那么你就知道你正在取得进展。

所以,打破仪器,开始测量。 如果可以的话,最好在你想要加速的每一个不同的活动中进行测量……在滚动的同时进行一个分析会话,一个在固定的时间内select尽可能多的不同的单元格等等。不要忘记保存结果,以便以后可以进行比较。

只要注意这些点

  1. 你正在重复使用细胞..这是一个很好的做法..
  2. 确保你没有在cellForRowAtIndexPathcallback中进行任何昂贵的计算,或者从CellForRowAtIndexPath中调用一个函数。
  3. 你说有一个背景图片。 你必须重用你的手机的另一个原因。

关于细胞再利用的一些很好的信息在这里

编辑:发现这个页面很晚..

这SO问题线程可能会帮助你…尤其是接受的答案…

  1. 为后台使用一个共享的图像实例(每次创build一个新的单元时,都会为其分配/ init / release)。 当你的表格视图很大的时候,这意味着内存中的背景X单元需要更多的内存。

    代替
    cell.backgroundView= [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cell gradient2.png"]];
    只是使用:
    cell.backgroundView= [SomeHelperClass sharedBackgroundUIImageResource];

  2. 如果这没有帮助,使用CG而不是标签和其他子视图(一个截图将有助于这里..知道我们在说什么)。

表视图的委托实现:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 

如果是这样,你可能希望考虑设置你的UITableViewCell的rowHeight属性。

你使用了很多子视图吗?

如果是这样,一个好的技术是,而不是添加大量的标签和图像,使用CoreGraphics绘制它们。

要做到这一点,你必须-(void)drawRect:(CGRect)rect UITableViewCell并实现-(void)drawRect:(CGRect)rect方法。

两个build议:一个是使用-initWithStyle:reuseIdentifier:为您的表格视图单元格而不是-initWithFrame :. 另一个是注释掉设置cell.backgroundView到一个梯度的图像,看看是不是罪魁祸首。 每次我在表格视图中performance不佳时,都是因为图像。

这是一个小题目(因为你只有一个背景图像的所有单元格):

我的应用在每个单元中显示不同的图像。 在向UITableView添加大约5个单元之后,表格大大减慢。 每次打开视图控制器大约需要1-2秒的时间处理所有图像。

 if let image = UIImage(contentsOfFile: photoFile){ // just set it and let system fit it //cell.imageView!.image = image // 1 - Calculate sized let DEFAULT_THUMBNAIL_WIDTH: CGFloat = (cellHeight / 4) * 5; let DEFAULT_THUMBNAIL_HEIGHT: CGFloat = cellHeight; let aspectRatio: CGFloat = image.size.width / image.size.height var willBeHeight = DEFAULT_THUMBNAIL_HEIGHT var willBeWidth = DEFAULT_THUMBNAIL_HEIGHT * aspectRatio if(willBeWidth > DEFAULT_THUMBNAIL_WIDTH){ willBeWidth = DEFAULT_THUMBNAIL_WIDTH willBeHeight = willBeWidth / aspectRatio } let eps:CGFloat = 0.000001 assert((willBeHeight - eps) <= DEFAULT_THUMBNAIL_HEIGHT); assert((willBeWidth - eps) <= DEFAULT_THUMBNAIL_WIDTH); // 2 - Create context var size:CGSize = CGSize( width: DEFAULT_THUMBNAIL_WIDTH, height: DEFAULT_THUMBNAIL_HEIGHT) UIGraphicsBeginImageContext(size) // one-to-one rect //var imageRect: CGRect = CGRectMake(0.0, 0.0, size.width, size.height) var imageRect: CGRect = CGRectMake(0.0, 0.0, willBeWidth, willBeHeight) // 3 - Draw image image.drawInRect(imageRect) var imageResult: UIImage = UIGraphicsGetImageFromCurrentImageContext() cell.imageView!.image = imageResult UIGraphicsEndImageContext() }else{ DDLogError("Can not draw photo: \(photoFile)") } 

所以我已经结束了为我所有的图像生成小THUMBNAILS。

重用单元格。 对象分配具有性能成本,尤其是如果分配必须在短时间内重复发生,例如当用户滚动表视图时。 如果您重复使用单元格而不是分配新单元格,则可大大提高表视图性能。 避免重播内容。 当重复使用自定义子视图的单元格时,请避免在每次表视图请求单元格时布置这些子视图。 在创build单元格时,将子视图布置一次。 使用不透明的子视图。 定制表格视图单元格时,使单元格的子视图不透明,不透明。