优化UITableView性能
2016-01-15 13:18
489 查看
首先了解下UITableView的核心功能:UITableViewCell的重用机制。简单的说就是UITableView初次创建手机屏幕或者屏幕多一点点的UITableViewCell;每当cell滑出屏幕时,UITableView会将已创建的cell收录到一个集合中(数组或者字典),这个集合就相当于一个重用池;当要显示某一条cell时,会先从重用池中取,如果有的话直接拿来显示,没有则创建
了解重用机制后,在来关注下UITableView的两个回调方法:cellForRowAtIndexPath和heightForRowAtIndexPath;
理论来说UITableView会先调用前者,再调用后者,但事实并非如此。UITableView是继承自UIScrollView的,需要先确定它的contentSize及每个Cell的位置,然后才会把重用的Cell放置到对应的位置。所以事实上,UITableView的回调顺序是先多次调用heightForRowAtIndexPath:以确定contentSize及Cell的位置,然后才会调用cellForRowAtIndexPath:,从而来显示在当前屏幕的Cell。
举个例子来说:如果现在要显示100个Cell,当前屏幕显示5个。那么加载更多cell时,UITableView会先调用100次heightForRowAtIndexPath:方法,然后调用5次cellForRowAtIndexPath:方法;滚动屏幕时,每当Cell滚入屏幕,都会调用一次heightForRowAtIndexPath:、cellForRowAtIndexPath:方法。
下面分析下这段代码
根据上面的例子,我的优化思路是:因为
heightForRowAtIndexPath 先于 cellForRowAtIndexPath 调用。那么在 heightForRowAtIndexPath 的时候初始化 cell,缓存起来。
cellForRowAtIndexPath 的时候,从缓存读取。
了解重用机制后,在来关注下UITableView的两个回调方法:cellForRowAtIndexPath和heightForRowAtIndexPath;
理论来说UITableView会先调用前者,再调用后者,但事实并非如此。UITableView是继承自UIScrollView的,需要先确定它的contentSize及每个Cell的位置,然后才会把重用的Cell放置到对应的位置。所以事实上,UITableView的回调顺序是先多次调用heightForRowAtIndexPath:以确定contentSize及Cell的位置,然后才会调用cellForRowAtIndexPath:,从而来显示在当前屏幕的Cell。
举个例子来说:如果现在要显示100个Cell,当前屏幕显示5个。那么加载更多cell时,UITableView会先调用100次heightForRowAtIndexPath:方法,然后调用5次cellForRowAtIndexPath:方法;滚动屏幕时,每当Cell滚入屏幕,都会调用一次heightForRowAtIndexPath:、cellForRowAtIndexPath:方法。
下面分析下这段代码
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { asd *cell = (asd *)[tableView cellForRowAtIndexPath:indexPath]; return cell.frame.size.height; }注:高版本中会编译出错
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *identifier = [NSString stringWithFormat:@"%ld%ld",indexPath.row,indexPath.section]; asd *cell = [_table dequeueReusableCellWithIdentifier:identifier]; if(!cell){ cell = [[asd alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; } cell.label.text = identifier; [cell setCellFrame]; return cell; }这样写法看似很巧妙,但只是简单cell,如果是复杂cell,直接卡到呵呵呵了...
根据上面的例子,我的优化思路是:因为
heightForRowAtIndexPath 先于 cellForRowAtIndexPath 调用。那么在 heightForRowAtIndexPath 的时候初始化 cell,缓存起来。
cellForRowAtIndexPath 的时候,从缓存读取。
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [self customCreateCell:indexPath]; return cell.frame.size.height; }
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { return [self customCreateCell:indexPath]; }
-(UITableViewCell *)customCreateCell:(NSIndexPath *)indexPath { NSString *identifier = [NSString stringWithFormat:@"%ld%ld",indexPath.row,indexPath.section]; //查找有没有缓存 asd *cell = (asd *)[_dataDic objectForKey:identifier]; if(!cell){ //没有的话调用tableView的重用机制 cell = [_table dequeueReusableCellWithIdentifier:identifier]; if(!cell){ cell = [[asd alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; } cell.label.text = identifier; [cell setCellFrame]; [self.dataDic setObject:cell forKey:identifier]; } return cell; }
相关文章推荐
- Qt使用教程之创建Qt Quick应用程序(一)
- UITableViewCell 自定义
- Android酷炫实用的开源框架(UI框架)
- hdoj5496Beauty of Sequence
- UITextField-secureTextEntry
- LeetCode Permutation Sequence
- 监听UITextField的内容变化,获取键盘的模式
- Effective Java,Item2——Consider a builder when faced with many constructor parameters
- iOS开发UI篇—CAlayer层的属性
- Ado.Net小练习02(小项目CUID
- Ado.Net小练习02(小项目CUID
- Android UI布局之RelativeLayout
- 【leetcode】206. Reverse Linked List My Submissions Question
- UE4 WCF RestFul 服务器 读取JSON 数据并解析 简单实例
- RabbitMQ入门教程 For Java【2】 - Work Queues
- 使用druid连接池的超时回收机制排查连接泄露问题
- Druid连接池一个设置引发的血案
- 最大团算法(Maximum Clique)
- UE4代码文件结构的正确配置
- ios中UIControl详解