UITableView中的cell重用(原理)以及cell重用解决办法
2016-03-20 23:11
591 查看
一、cell重用原理
对于UITableView中系统的cell,一般会通过重用cell来达到节省内存的目的:通过为每个cell指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,当cell滚出屏幕时,会将滚出屏幕的单元格放入重用的queue中,当某个未在屏幕上的单元格要显示的时候,就从这个queue中取出单元格进行重用。
即调用dequeueReusableCellWithIdentifier方法来实现。代码如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = [NSString stringWithFormat:@"cell"];
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
cellIdentifier] autorelease];
}
return cell;
}
例如:一个table中有20个cell,但是屏幕上最多只能显示10个cell,那么在实际上系统只为其分配了10个cell的内存。当滚动屏幕时,屏幕内显示的cell重复使用这10个cell的内存。
之前有参考过一些资料,解释:在UITableView的头文件中,会找到NSMutableArray *visiableCells,和NSMutableDictionary *reusableTableCells两个结构。visiableCells保存当前显示的cells,reusableTableCells保存可重用的cells。
TableView显示之初,reusableTableCells为空,那么dequeueReusableCellWithIdentifier方法返回nil。开始的10个cell都会走 if(cell == nil) 判断(这里可打断点调试)
通过[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]来创建,并给cell指定同样的重用标识,10个cell全部都加入到visiableCells数组,reusableTableCells为空。
向下拖动tableView,当cell1完全移出屏幕,且cell11完全显示在屏幕上时,cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。之后的cell都是如此。也许这是比较古老的tableView的头文件,现在搜了一下,貌似找不到这两个容器。
二、cell重用解决办法
对于一些自定义的cell,使用重用机智就会导致出错,因此给出以下两种解决重用机制的方法:
1、通过调用cellForRowAtIndexPath方法根据indexPath准确地取出一行
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
static NSString *cellIdentifier = @"cell";
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; //改为以下的方法
UITableViewCell *cell =[tableView cellForRowAtIndexPath:indexPath];
//根据indexPath准确地取出一行,而不是从cell重用队列中取出
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
return cell;
}
2、为每个cell指定不同的重用标识符(reuseIdentifier)
- (UITableViewCell
*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier =[NSString stringWithFormat:@"cell%d%d", [indexPath section], [indexPath row]];//以indexPath来唯一确定cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; //出列可重用的cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
return cell;
}
对于UITableView中系统的cell,一般会通过重用cell来达到节省内存的目的:通过为每个cell指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,当cell滚出屏幕时,会将滚出屏幕的单元格放入重用的queue中,当某个未在屏幕上的单元格要显示的时候,就从这个queue中取出单元格进行重用。
即调用dequeueReusableCellWithIdentifier方法来实现。代码如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = [NSString stringWithFormat:@"cell"];
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
cellIdentifier] autorelease];
}
return cell;
}
例如:一个table中有20个cell,但是屏幕上最多只能显示10个cell,那么在实际上系统只为其分配了10个cell的内存。当滚动屏幕时,屏幕内显示的cell重复使用这10个cell的内存。
之前有参考过一些资料,解释:在UITableView的头文件中,会找到NSMutableArray *visiableCells,和NSMutableDictionary *reusableTableCells两个结构。visiableCells保存当前显示的cells,reusableTableCells保存可重用的cells。
TableView显示之初,reusableTableCells为空,那么dequeueReusableCellWithIdentifier方法返回nil。开始的10个cell都会走 if(cell == nil) 判断(这里可打断点调试)
通过[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]来创建,并给cell指定同样的重用标识,10个cell全部都加入到visiableCells数组,reusableTableCells为空。
向下拖动tableView,当cell1完全移出屏幕,且cell11完全显示在屏幕上时,cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。之后的cell都是如此。也许这是比较古老的tableView的头文件,现在搜了一下,貌似找不到这两个容器。
二、cell重用解决办法
对于一些自定义的cell,使用重用机智就会导致出错,因此给出以下两种解决重用机制的方法:
1、通过调用cellForRowAtIndexPath方法根据indexPath准确地取出一行
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
static NSString *cellIdentifier = @"cell";
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; //改为以下的方法
UITableViewCell *cell =[tableView cellForRowAtIndexPath:indexPath];
//根据indexPath准确地取出一行,而不是从cell重用队列中取出
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
return cell;
}
2、为每个cell指定不同的重用标识符(reuseIdentifier)
- (UITableViewCell
*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier =[NSString stringWithFormat:@"cell%d%d", [indexPath section], [indexPath row]];//以indexPath来唯一确定cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; //出列可重用的cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
return cell;
}
相关文章推荐
- UI 进阶总结
- UE/UI/UCD/UED 区别
- 单线程模型中Message,Handler,MessageQueue,Looper之间的关系
- CoordinatorLayout使用方法
- map、set、vector、list、stack、queue、deque、priority_queue
- UIScrollView的滑动视图切换(懒加载)
- Django Cross Site Request Forgery protection
- queue service bus
- Java - GUI
- iOS 最新UIAlertController
- AndrodUI优化之布局优化
- FineUI LINQ TO SQL 数据库分页查询
- CVImageBufferRef转UIImage
- Building an Informatio…
- Building an Informatio…
- Building an Informatio…
- The type java.lang.reflect.AnnotatedElement cannot be resolved. It is indirectly referenced from required .class files
- c#在windows form开发时多线程对UI…
- GPUImage使用简介
- 安卓开发经验分享:资源、UI、函数库、测试、构建一个都不能少(转)