TableViewCell reuse 重用 我认为的正确理解与使用方法

其实有点失望,因为用google搜索“uitableviewcell dequeueReusableCellWithIdentifier”出来一堆堆资深博主的文章。看了看,大部分都是在解决一个问题:使用重用时cell显示混乱的问题。该问题本身并不让我失望,失望的是博主们的解释。

首先,回顾一下UITableViewCell的重用,其基本逻辑就是tableView一开始会创建一屏幕的cell(如果有那么多)并把他们标记(Identifier),之后用户上下滑动tableView时,使用Identifier获取移出去的cell,将其用作新移进来的cell重新被赋予内容,再显示出来,这样就完成了cell重用,目的是优化内存。现在,我并不对其原理做再深入的探究,只是知道以上这些大概的逻辑。(欢迎探讨,以及指出你认为我可能理解错的地方)

问题来了,我在工作中、或是在前文提到的资深博主文章里会经常会看到有人说重用发生问题,新移入的cell有时会显示出刚刚移除去的cell的内容,或者干脆就在滑动的过程中cell显示完全混乱了。于是他们有写人就创造了一些方法和解释。比如:

http://www.cnblogs.com/lihaibo-Leao/p/3471556.html

http://blog.csdn.net/hmt20130412/article/details/20860049

http://blog.csdn.net/joiningss/article/details/6702023

http://blog.csdn.net/winsdom123456/article/details/7363383

各种解决方案归纳一下无外乎:

1,重用遇到界面混乱,这是个常见问题!我们就要使用多种的方法来干掉这个重用机制。(某博主原话,无力吐槽。。。)

2,既然重用有问题,那么我们就不重用了,有多少数据,就创建多少cell。

3,重用归重用,但是identifier用不同的(好自欺欺人啊= =#)

4,重用归重用,但我每次设置cell上的subView内容时,先删除上面的所有subView,再重新创建。

遇到问题解决问题、分享解决方法这是好的,但是这里他们忽略了几个问题:

1,iOS为什么一定要重用?重用优化内存,这是apple的全职工程师研究出来的东西,你能轻易否定它吗?

2,identifier是用来标记可被重用的cell的队列的,如果你使用不同的标记来标记cell,创建的时候也使用不同的标记创建,这是自欺欺人的,实际上也没用重用;

3,每次删除,再创建subView,看起来比较保险,也算是几个解决方案中最靠谱的方法了。。。但其实,这对效率是一种损失。重用机制本来就是希望优化内存,优化界面体验,你删除再创建,增加不必要的工作量,就与这一理念背道而驰。

吐槽完毕,现在我利用一个demo(在这里可以看到https://github.com/pigpigdaddy/TableViewTestDemo)解释一下我理解的正确的cell重用

先介绍一下demo:我创建了一个空项目,又创建了三个类,

类ViewController,用于window的rootViewController,

类TableViewTestView,在这里面创建tableview,

类DemoTableViewCell,继承自UITableViewCell,里面有一个label,加在了cell的contentView上。

在ViewController创建TableViewTestView的实例,再在TableViewTestView里创建tableView,实现各种tableView的回调、数据源。用的cell是DemoTableViewCell (具体还请一定去https://github.com/pigpigdaddy/TableViewTestDemo看源代码,很简单,我就不对每个函数做做完全的说明了)

那么正确的重用应该是:

1,首先,用户滑动tableview,在每次刷新新的cell时会自动调用

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *),你应该老老实实地去实现它

 1 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 2 {
 3     return self.dataSource.count;
 4 }
 5
 6 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 7 {
 8     static NSString *cellIdentifier = @"DemoTableViewCell";
 9     DemoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
10     if (!cell) {
11         cell = [[DemoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
12     }
13
14     [cell loadData:[self.dataSource objectAtIndex:indexPath.row]];
15
16     return cell;
17 }

2,每次调用该函数时,就像我们所知道的那样,先去根据identifier去寻找“队列里”是否有可以重用的cell,如果没有,则创建一个新的,所用的identifier是同一个!

3,刷新数据,你只需要调用我自定义cell里的函数

- (void)loadData:(NSDictionary *)data;

1 [cell loadData:[self.dataSource objectAtIndex:indexPath.row]];

该函数负责修改label的text,你不需要先删除,在重新创建label,完全不需要。

4,那么label应该在哪里创建呢?在cell初始化的地方创建:

 1 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
 2 {
 3     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
 4     if (self) {
 5         // Initialization code
 6         self.labelTest = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 24)];
 7         [self.contentView addSubview:self.labelTest];
 8     }
 9     return self;
10 }

像这样,仅仅在这个cell被创建的时候,创建labelText,以后刷新到这个cell,只需要调用loadData这个函数,用相应的数据去刷新label内容就可以了!只要你正确刷新数据,显示就不会有问题!

运行程序,上下滑动,完全没有问题!

自定义的cell有再多的subView,这些subView只在cell创建的时候创建,其余时候刷新cell,只需要loadData刷新数据,刷新subView显示内容就可以了,就是这么简单!

再也不用担心会混乱,再也不用找各种方法去规避“重用机制”了。希望大家曾经发生混乱的都去试试!

写的不对的地方请多包涵,并帮忙指出,感谢!

TableViewCell reuse 重用 我认为的正确理解与使用方法,布布扣,bubuko.com

时间: 2024-11-03 22:43:33

TableViewCell reuse 重用 我认为的正确理解与使用方法的相关文章

if __name__ == '__main__' 如何正确理解

今天刷知乎,突然看到这个问题,发现很多人都是简单的回答了一下,对于很多人来说,更准确的说应该是大部分的 Python 初学者,这样的回答很容易让人理解.所以这里我来做说一下,希望能把这个问题说明白. 先举一个例子:假设我们有一个add.py文件,里面的代码是这样: def add(a, b):    return a + badd(1,2)#用于测试上面函数是否正常 这里就是一个求两数之和的函数,然后我在另一个文件中调用这个模块,这个时候就会把add(1,2)也运行,但是我是不希望运行add(1

正确理解Python函数是第一类对象

正确理解 Python函数,能够帮助我们更好地理解 Python 装饰器.匿名函数(lambda).函数式编程等高阶技术. 函数(Function)作为程序语言中不可或缺的一部分,太稀松平常了.但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性.那到底什么是第一类对象呢? 函数是对象 在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量.可以作为元素添加到集合对象中.可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性

正确理解“冬钓阴”和“冬钓阳”

转载请注明文章转载自 光威鱼竿价格表 冬季钓鱼一般都讲究冬钓阳,但是又有一种说法叫做冬钓阴,这里面咋一看有点矛盾,那么怎么来正确理解这两者呢? 先来说说什么是冬钓阴,冬钓阴可不是选择阴天出去钓鱼,在冬天,如果没有太阳的话,一般水面受冷风侵袭,水温会比较低,不大利于鱼的活动和觅食,而另外一些地方,比如岸边有密集树林或者有挡风的围墙等等,这些平时觉得比较阴暗地方的水面由于被挡住了风,所以水温会相对高一些,更适合鱼活动,选择这些个地方垂钓就是所谓的冬钓阴. 冬钓阳,顾名思义就是选择有太阳的日子出去钓鱼

正确理解SQL Server配置timeout相关选项

正确理解SQL Server配置选项"remote login timeout"和"remote query timeout" 查看配置选项的设置 sp_configure 远程登录超时 参考:https://msdn.microsoft.com/en-us/library/ms175136.aspx "The remote login timeout option specifies the number of seconds to wait befor

IOS开发UITableView性能应用技巧TableViewCell的重用

?iOS设备的内存有限,如果用UITableView显示成千上万条数据,就需要成千上万个UITableViewCell对象的话,那将会耗尽iOS设备的内存.要解决该问题,需要重用UITableViewCell对象??重用原理:当滚动列表时,部分UITableViewCell会移出窗口,UITableView会将窗口外的UITableViewCell放入一个对象池中,等待重用.当UITableView要求dataSource返回UITableViewCell时,dataSource会先查看这个对象

正确理解 LEAL (Load Effective Address) 指令

LEAL: leal S, D    ->    D ← &S 在 CSAPP (Computer Systems: A Programmer’s Perspective) 中,对 LEAL 指令用作简单算术运算的情况,给出了一个例子: For example, if register %edx contains value x, leal 7(%edx,%edx,4), %eax will set register %eax to 5x + 7. 正确理解逻辑为: 1. 设%edx的值为x

正确理解功率MOSFET的RDS(ON)温度系数特性

通常,许多资料和教材都认为,MOSFET的导通电阻具有正的温度系数,因此可以并联工作.当其中一个并联的MOSFET的温度上升时,具有正的温度系数导通电阻也增加,因此流过的电流减小,温度降低,从而实现自动的均流达到平衡.同样对于一个功率MOSFET器件,在其内部也是有许多小晶胞并联而成,晶胞的导通电阻具有正的温度系数,因此并联工作没有问题.但是,当深入理解功率MOSFET的传输特性和温度对其传输特性的影响,以及各个晶胞单元等效电路模型,就会发现,上述的理论只有在MOSFET进入稳态导通的状态下才能

正确理解HTML,XHTML页面的头部doctype定义

摘自http://www.west263.com/info/html/wangyezhizuo/css/20080225/42390.html 当我们制作页面的时候,总会在它的源码头部看到一串声明,比如最常见的 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 如

正确理解WPF中的TemplatedParent

(注:Logical Tree中文称为逻辑树,Visual Tree中文称为可视化树或者视觉树,由于名称不是很统一,文中统一用英文名称代表两个概念,况且VisualTreeHelper和LogicalTreeHelper也是WPF中提供的类名称) 众所周知WPF中的Logical Tree是逻辑上定义的元素层次树,而实际上显示在屏幕上的元素层次树是Visual Tree,Visual Tree是 (注:Logical Tree中文称为逻辑树,Visual Tree中文称为可视化树或者视觉树,由于