Table Data Source Methods中的一个必要实现的方法tableView: cellForRowAtIndexPath: 中经常会包含一段代码:
  1. static NSString *FirstLevelCell = @"FirstLevelCell";
  2. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
  3. FirstLevelCell];   //此方法创建所有行样式均相同
  4. if (cell == nil) {
  5. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault  reuseIdentifier: FirstLevelCell];
  6. //如果cell为空,则调用此方法创建一个StyleDefault风格,重用识别符为@"FirstLevelCell"的protocell
  7. }

第一行是设置了一个字符串标识。

第二行起是关键,翻看官方文档中关于方法dequeueReusableCellWithIdentifier:的说明:

For performance reasons, a table view'€™s data source should generally reuse UITableViewCell objects when it assigns cells to rows in its tableView:cellForRowAtIndexPath: method. A table view maintains a queue or list of UITableViewCell objects that the data source has marked for reuse. Call this method from your data source object when asked to provide a new cell for the table view. This method dequeues an existing cell if one is available or creates a new one using the class or nib file you previously registered. If no cell is available for reuse and you did not register a class or nib file, this method returns nil.

If you registered a class for the specified identifier and a new cell must be created, this method initializes the cell by calling its initWithStyle:reuseIdentifier: method. For nib-based cells, this method loads the cell object from the provided nib file. If an existing cell was available for reuse, this method calls the cell’s prepareForReuse method instead.

翻译一下 大意就是:

出于性能的原因,一个表视图的数据源应该采用可复用的表视图单元对象。一个表视图维护着一个可复用单元的队列或者列表。当要显示一个新的单元的时候就调用这个方法,这个方法会出列一个已经存在的单元。假如没有可以复用的单元那么就返回nil。

说实话不大清楚。还是从表视图的生命周期来说,一开始可复用队列为空,调用dequeueReusableCellWithIdentifier:肯定返回nil。然后就调用initWithStyle:reuseIdentifier:方法来产生并且标识复用记号的表视图单元。满屏显示的时候,滚动表视图,一侧的单元就会被移出屏幕,此时这个单元进入可复用单元队列,然后调用prepareForReuse方法准备一个即将出列的单元, dequeueReusableCellWithIdentifier:从可复用单元队列里出列一个可复用单元。

表视图里可能有不同类型的单元,复用是在相同类型单元里发生的。至于队列里有多少单元,这个系统自己控制,如果内存紧张,就会动态释放掉一些,当条件改善的时候,就会重新获取这些单元便于复用。一个极端的情况,可复用的单元没有了,那么又会调用initWithStyle:reuseIdentifier:来产生新的单元。理解表视图的机制,不能把思维定在严格的队列机制里,它有些动态的因素需要考虑。

此外在if语句后面的操作算是重用更新,if语句里的操作应该是新造。

移动开发:dequeueReusableCellWithIdentifier的运行机制

dequeueReusableCellWithIdentifier消息返回的是UITableViewCell对象,即是说这是一个用来获取UITableViewCell对象的消息,废话。
之所以不说是初始化一个对象,是因为它可能返回nil值,所以才要在下面补充一个如果cell为nil时的处理过程。
那么这个方法是不是可以解释成为,从一个UITableViewCell对象池中获取一个以Identifier参数命名的UITableViewCell对象。
如果在资源紧缺的时候,这个池会自动清理多余的UITableViewCell对象,则可能无法返回对象,但如果资源丰富,则会保存一些UITableViewCell对象,在需要调用的时候迅速的返回,而不用创建。

dequeueReusableCellWithIdentifier,从字面上理解是“出列可重用的cell”,其实简单说就是一个cell池,里面放的就是你之前创建过的cell。使用时要注意:
1。重取出来的cell是有可能已经捆绑过数据或者加过子视图的,所以,如果有必要,要清除数据(比如textlabel的text)和remove掉add过的子视图(使用tag)。
2。这样设计的目的是为了避免频繁的 alloc和delloc cell对象而已,没有多复杂。
3。设计的关键是实现cell和数据的完全分离

关键点在"一个屏幕显示的cell数量"是有限的
当屏幕滚动时候,就会调用方法获取新的cell,而老的cell会在屏幕外面就不显示了

reuse机制就是这样。。当cell需要显示的时候,从queue里面找,找到了,设置一下内容,显示出来
滚动界面当有cell被移出屏幕时,把这个cell丢到queue里面
显示新的cell时,如果有“相同类型”(identifier)的cell,就从队列拿一个出来,设置数据,显示出来
至于queue里面会有多少cell,这个会自动控制

要注意的是,queue里面存储的是cell的实例,不是“原型”
因此就会出现上面说的“假设每页有 5个。 则 第6个复用第1个cell; 第7个复用第2个;”
这样的结果是不管你的table有多少行,内存里实际上都只需要存储一个屏幕那么多行的cell就搞定了。。

05-11 17:05