UITableViewCell的重用机制
简介
UITableView相信对于诸多的从事IOS开发的人来说已经是非常熟悉的了,可以说iPhone很多应用都有使用,应该来说是一个比较频繁的组件了,对于它的很多使用技巧,我们今天就不做讨论了,这里主要说的是UITableViewCell的重用机制。
对于一个好的应用开发来说,系统的架构是很重要的,必须清晰明了,各部分设计必须分工明确。比如现在很流行的MVC系统架构。把视图、模型、控制都分割开来。其实UITableViewCell设计思想也是这样的,开发者必须明白,要想达到一个很好的cell复用效果,那么我们就必须明白,把cell和数据分割开来。要是我们明白这点,那么我们在进行cell复用的时候思路就很清晰了。并且可以规避掉我们初学者看起来很无厘头的bug。比如在进行上下滑动的时候,cell重复显示了以前的,这并不是我们想看到的。
原理
首先我们先看段代码
我们先解释一下基本的意思,首先呢我们给我们的cell取一个名字叫“Cell”,在创建的时候呢,我们先去复用容器(暂且这样说,实际上复用的cell是放在NSMutableDictnery这种容器里边的)里边根据名字寻找有没有叫“Cell”的TableViewCell,如果没有找到,那么我们就去创建一个叫“Cell”的TableViewCell,我想这样解释还算合理吧。
下面我们就要说说复用的时机和原理了,其实UITableView的头文件里边有这么两个东西NSMutableArray visiableCells,和NSMutableDictnery reusableTableCells两个结构。其中visiableCells内保存当前显示的cells,reusableTableCells保存可重用的cells。TableView显示之初,reusableTableCells为空,那么tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。开始的cell都是通过[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]来创建,而且cellForRowAtIndexPath只是调用最大显示cell数的次数。明白了吧,其实开始显示的时候创建了一屏显示的UITableViewCell。
比如:有30条数据,iPhone一屏最多显示10个cell。程序最开始显示TableView的情况是:
1. 用[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]创建10次cell,并给cell指定同样的重用标识(当然,可以为不同显示类型的cell指定不同的标识)。并且10个cell全部都加入到visiableCells数组,reusableTableCells为空。
2. 向下拖动tableView,当cell1完全移出屏幕,并且cell11(它也是alloc出来的,原因同上)完全显示出来的时候。cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。
3. 接着向下拖动tableView,因为reusableTableCells中已经有值,所以,当需要显示新的cell,cellForRowAtIndexPath再次被调用的时候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出visiableCells,cell2加入到reusableTableCells。之后再需要显示的Cell就可以正常重用了。
cell的复用流程这下就清楚了,但是,有一点需要注意的是我们需要对重用的cell做从新赋值,不要出现遗留老数据的情况,如果遗留了老数据,那么我们看到的cell就是以前使用过的相同cell。这事有一个解决办法
删除重用的cell的所有子视图,从而得到一个没有特殊格式的cell,供其他cell重用,我们从新加入数据源。
注意及技巧
这里还有两点需要注意的是reloadData操作和指定cell的reload操作(reloadRowsAtIndex)
1. reloadData,这种情况比较特殊。一般是部分数据发生变化,需要重新刷新cell显示的内容时调用。在cellForRowAtIndexPath调用中,所有cell都是重用的。我估计reloadData调用后,把visiableCells中所有cell移入reusableTableCells,visiableCells清空。cellForRowAtIndexPath调用后,再把reuse的cell从reusableTableCells取出来,放入到visiableCells。
2. reloadRowsAtIndex,刷新指定的IndexPath。如果调用时reusableTableCells为空,那么cellForRowAtIndexPath调用后,是新创建cell,新的cell加入到visiableCells。老的cell移出visiableCells,加入到reusableTableCells。于是,之后的刷新就有cell做reuse了。
这里还给大家介绍一个cell的使用技巧,当然这不是复用cell的技巧,而是不复用cell的技巧,有的时候,我们为了应对我们的需求,要求我们所使用的cell每个都不相同,甚至差别还很大,这时要求我们对每个cell进行定制,那么技巧来了。
是不是很机制,这样就永远也不可能找得到相同名字的cell了,也就是说复用功能在这里就被巧妙的避免了。