详细整理iOS中UITableView的性能优化

一、介绍

iOS开发中,UITableView可能是平时我们打交道最多的UI控件之一,其重要性不言而喻。Android也是如此,Android中的ListView和UITableView是相同功能的一个控件,但是iOS的UITableView更为强大一点,原因就不说了,如果你学过Android就知道iOS中的UITableView使用起来是非常简单的,这也是峰哥喜欢iOS胜过Android的原因之一。今天研究的内容就是UITableView的优化。

开始之前,你能说出几种UITableView的可优化项?cell复用(Android中经常称为ListView的重用,其实重用复用都是一个意思,由于峰哥之前做过Android的原因,有时候我经常说“重用”,后面万一说“重用”大家知道是“复用”的意思就行了)!除了cell重用呢?

二、UITableView的性能优化

1、cell复用

复用很简单,这或许是所有iOS开发者最为熟知的一个优化内容,如下代码:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 static NSString *Identifier = @"cell";
 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
 if (!cell) {
 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
 }

 return cell;
}

但是,这样重用就完美了吗?

我们经常在注意cellForRowAtIndexPath:中为每一个cell绑定数据,实际上在调用cellForRowAtIndexPath:的时候cell还没有被显示出来,为了提高效率我们应该把数据绑定的操作放在cell显示出来后再执行,可以在tableView:willDisplayCell:forRowAtIndexPath:(以后简称willDisplayCell)方法中绑定数据。

注意willDisplayCell在cell 在tableview展示之前就会调用,此时cell实例已经生成,所以不能更改cell的结构,只能是改动cell上的UI的一些属性(例如label的内容等)。

2、cell高度的计算

这边我们分为两种cell,一种是定高的cell,另外一种是动态高度的cell。

(1)定高的cell,应该采用如下方式:

self.tableView.rowHeight = 88;

这个方法指定了所有cell高度都是88的tableview,rowHeight默认的值是44,所以一个空的TableView会显示成这个样子。对于定高cell,直接采用上面方式给定高度,不需要实现tableView:heightForRowAtIndexPath:以节省不必要的计算和开销。

(2)动态高度的cell

我们需要实现它的代理,来给出高度:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
 // return xxx
}

这个代理方法实现后,上面的rowHeight的设置将会变成无效。在这个方法中,我们需要提高cell高度的计算效率,来节省时间。

自从iOS8之后有了self-sizing cell的概念,cell可以自己算出高度,使用self-sizing cell需要满足以下三个条件:

(1)使用Autolayout进行UI布局约束(要求cell.contentView的四条边都与内部元素有约束关系)。

(2)指定TableView的estimatedRowHeight属性的默认值。

(3)指定TableView的rowHeight属性为UITableViewAutomaticDimension。

- (void)viewDidload {
 self.myTableView.estimatedRowHeight = 44.0;
 self.myTableView.rowHeight = UITableViewAutomaticDimension;
}

除了提高cell高度的计算效率之外,对于已经计算出的高度,我们需要进行缓存,对于已经计算过的高度,没有必要进行计算第二次。

3、渲染

为了保证TableView的流畅,当快速滑动的时候,cell必须被快速的渲染出来。所以cell渲染的速度必须快。如何提高cell的渲染速度呢?

(1)当有图像时,预渲染图像,在bitmap context先将其画一遍,导出成UIImage对象,然后再绘制到屏幕,这会大大提高渲染速度。具体内容可以自行查找“利用预渲染加速显示iOS图像”相关资料。

(2)渲染最好时的操作之一就是混合(blending)了,所以我们不要使用透明背景,将cell的opaque值设为Yes,背景色不要使用clearColor,尽量不要使用阴影渐变等

(3)由于混合操作是使用GPU来执行,我们可以用CPU来渲染,这样混合操作就不再执行。可以在UIView的drawRect方法中自定义绘制。

4、减少视图的数目

我们在cell上添加系统控件的时候,实际上系统都会调用底层的接口进行绘制,大量添加控件时,会消耗很大的资源并且也会影响渲染的性能。当使用默认的UITableViewCell并且在它的ContentView上面添加控件时会相当消耗性能。所以目前最佳的方法还是继承UITableViewCell,并重写drawRect方法。

5、减少多余的绘制操作

在实现drawRect方法的时候,它的参数rect就是我们需要绘制的区域,在rect范围之外的区域我们不需要进行绘制,否则会消耗相当大的资源。

6、不要给cell动态添加subView

在初始化cell的时候就将所有需要展示的添加完毕,然后根据需要来设置hide属性显示和隐藏。

7、异步化UI,不要阻塞主线程

我们时常会看到这样一个现象,就是加载时整个页面卡住不动,怎么点都没用,仿佛死机了一般。原因是主线程被阻塞了。所以对于网路数据的请求或者图片的加载,我们可以开启多线程,将耗时操作放到子线程中进行,异步化操作。这个或许每个iOS开发者都知道的知识,不必多讲。

8、滑动时按需加载对应的内容

如果目标行与当前行相差超过指定行数,只在目标滚动范围的前后指定3行加载。

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
 NSIndexPath *ip = [self indexPathForRowAtPoint:CGPointMake(0, targetContentOffset->y)];
 NSIndexPath *cip = [[self indexPathsForVisibleRows] firstObject];
 NSInteger skipCount = 8;
 if (labs(cip.row-ip.row)>skipCount) {
  NSArray *temp = [self indexPathsForRowsInRect:CGRectMake(0, targetContentOffset->y, self.width, self.height)];
  NSMutableArray *arr = [NSMutableArray arrayWithArray:temp];
  if (velocity.y<0) {
   NSIndexPath *indexPath = [temp lastObject];
   if (indexPath.row+33) {
    [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-3 inSection:0]];
    [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-2 inSection:0]];
    [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-1 inSection:0]];
   }
  }
  [needLoadArr addObjectsFromArray:arr];
 }
}

记得在tableView:cellForRowAtIndexPath:方法中加入判断:

if (needLoadArr.count>0&&[needLoadArr indexOfObject:indexPath]==NSNotFound) {
 [cell clear];
 return;
}

滑动很快时,只加载目标范围内的cell,这样按需加载(配合SDWebImage),极大提高流畅度。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • iOS应用中UITableView左滑自定义选项及批量删除的实现

    实现UITableView左滑自定义选项 当UITableView进入编辑模式,在进行左滑操作的cell的右边,默认会出现Delete按钮,如何自定义左滑出现的按钮呢? 只需要实现UITableView下面的这个代理方法. 复制代码 代码如下: - (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath

  • 详解iOS开发中UItableview控件的数据刷新功能的实现

    实现UItableview控件数据刷新 一.项目文件结构和plist文件 二.实现效果 1.说明:这是一个英雄展示界面,点击选中行,可以修改改行英雄的名称(完成数据刷新的操作). 运行界面: 点击选中行: 修改数据后自动刷新: 三.代码示例 数据模型部分: YYheros.h文件 复制代码 代码如下: // //  YYheros.h //  10-英雄展示(数据刷新) // //  Created by apple on 14-5-29. //  Copyright (c) 2014年 itc

  • 全面解析iOS应用中自定义UITableViewCell的方法

    有时候我们需要自己定义UITableViewCell的风格,其实就是向行中添加子视图.添加子视图的方法主要有两种:使用代码以及从.xib文件加载.当然后一种方法比较直观. 一.基本用法 我们这次要自定义一个Cell,使得它像QQ好友列表的一行一样:左边是一张图片,图片的右边是三行标签: 当然,我们不会搞得这么复杂,只是有点意思就行. 1.运行Xcode 4.2,新建一个Single View Application,名称为Custom Cell: 2.将图片资源导入到工程.为此,我找了14张50

  • iOS App中UITableView左滑出现删除按钮及其cell的重用

    UITableView的编辑模式 实现UITableView简单的删除功能(左滑出现删除按钮) 首先UITableView需要进入编辑模式.实现下面的方法,即使什么代码也不写也会进入编辑模式: 复制代码 代码如下: - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)index

  • 改变iOS应用中UITableView的背景颜色与背景图片的方法

    改变UITableView的header.footer背景颜色 改变UITableView的header.footer背景颜色,这是个很常见的问题.之前知道的一般做法是,通过实现tableView: viewForHeaderInSection:返回一个自定义的View,里面什么都不填,只设背景颜色.但是今天发现一个更简洁的做法: 对于iOS 6及以后的系统,实现这个新的delegate函数即可: 复制代码 代码如下: - (void)tableView:(UITableView *)table

  • IOS UITableViewCell详解及按钮点击事件处理实例

    IOS UITableViewCell详解及按钮点击事件处理 今天突然做项目的时候,又遇到处理自定义的UITableViewCell上按钮的点击事件问题.我知道有两种方式,可是突然想不起来之前是怎么做的了,好记性不如烂笔头,还是记录一下吧. 1.第一种方式给Button加上tag值 这里分为两种:一种是直接在原生的UITableViewCell上添加UIButton按钮,然后给UIButton设置tag值,然后在控制器里的方法里通过取数据,做界面跳转等.还是举个例子吧,省的回忆半天. - (UI

  • iOS开发中UITableview控件的基本使用及性能优化方法

    UITableview控件基本使用 一.一个简单的英雄展示程序 NJHero.h文件代码(字典转模型) 复制代码 代码如下: #import <Foundation/Foundation.h> @interface NJHero : NSObject /**  *  头像  */ @property (nonatomic, copy) NSString *icon; /**  *  名称  */ @property (nonatomic, copy) NSString *name; /**  

  • 详解iOS开发中UITableview cell 顶部空白的多种设置方法

    我知道没人会主动设置这个东西,但是大家一定都遇到过这个问题,下面总结下可能是哪些情况: 1, self.automaticallyAdjustsScrollViewInsets = NO; 这个应该是最常见而且不容易被发现的原因,起因是iOS7在Conttoller中新增了automaticallyAdjustsScrollViewInsets这个属性,当设置为YES时(默认YES),如果视图里面存在唯一一个UIScrollView或其子类View,那么它会自动设置相应的内边距,这样可以让scr

  • iOS应用开发中UITableView的分割线的一些设置技巧

    对于ios7,ios8及以上来说,调整UITableView的cell的分割线位置已经是相当不便,因为UITableView内部使用了margin layout. 其实只需要如下这样子就可以实现分割线的控制. 复制代码 代码如下: -(void)tableView:(UITableView )tableView willDisplayCell:(UITableViewCell )cell forRowAtIndexPath:(NSIndexPath *)indexPath {     // 下面

  • iOS开发之UITableView左滑删除等自定义功能

    前言 相信每位iOS开发者都知道UITableView的左滑删除功能非常的炫酷,有时候左滑需要的功能不止只有删除一个,有时候会有顶置之类的别的功能,这时候就需要我们自己定制左滑 示例代码 -(NSArray<UITableViewRowAction*>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewRowAction *rowActio

随机推荐