解析UITableViewCell的reuse有关问题

解析UITableViewCell的reuse问题

UITableView在iOS开发中会经常使用,对于行数很多的UITableView,可以通过UITableViewCell的重用,来保证执行效率。源码下载点击这里。

我们通过代码来探索UITableViewCell重用的实现,下面是一段使用UITableView的代码,

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"myCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    if (cell == nil) {
        
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewStyleGrouped reuseIdentifier:@"myCell"];
        UITextField *tf;
        tf = [[UITextField alloc] initWithFrame:CGRectMake(100, 10, 150, 40) ];
        tf.delegate = self;
        tf.borderStyle = UITextBorderStyleRoundedRect;
        [cell  addSubview:tf];
        [tf release];
        
        cell.textLabel.text = [NSString stringWithFormat:@"%d",indexPath.row];
    }
    
    // Configure the cell...
    
    return cell;
}
我们期待的是上下拖动UITableView,结果是这样

解析UITableViewCell的reuse有关问题

然而结果确实我们上下拖动后,都是

解析UITableViewCell的reuse有关问题

我们回到dequeueReusableCellWithIdentifier的定义

- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier;  // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.
使用委托来获取一个已经分配的cell,代替分配新的一个;在这个例子中,将当前屏幕下创建的Cell都先加入到对象池,这是对象池的內Cell的个数大致是8,当我们滑动TableView时,将使用dequeueReusableCellWithIdentifier方法返回对象,该方法通过

reuseIdentifier(“myCell”)在对象池中,查找之前已经放入的cell对象。

这时候就有了第一个解决方案,既然它重用出问题,就不让它重用,代码如下

NSString *CellIdentifier = [NSString stringWithFormat:@"myCell_%d",indexPath.row];
对于每一行,设定不同的reuseIdentifier。


CocoaTouch的开发人员也很与时俱进,在iOS6.0,终于有了新的方法

 //ios 6.0
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
 static NSString *CellIdentifier = @"myCell";
 
 [tableView registerClass:[UITableViewCell class]  forCellReuseIdentifier:CellIdentifier];
 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

 UITextField *tf;
 tf = [[UITextField alloc] initWithFrame:CGRectMake(100, 10, 150, 40) ];
 tf.delegate = self;
 tf.borderStyle = UITextBorderStyleRoundedRect;
 [cell  addSubview:tf];
 [tf release];
 
 cell.textLabel.text = [NSString stringWithFormat:@"%d",indexPath.row];
 // Configure the cell...
 
 return cell;
 }
我们先注册cell,然后再通过

- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); // newer dequeue method guarantees a cell is returned and resized properly, assuming identifier is registered

问题快被解决了,但是程序员总是有很多问题,比如现在的代码下,如果我们在UITextField输入了对应于textLabel的值(1、2、3、4。。。),再向下拖动,再拖回原来的位置,还可以看到UITextField內的数字么?我测试的结果是不能,我这里给出一个我的解决方法

     //添加目标动作对,使其值改变时,自动保存至变量
     [tf addTarget:self action:@selector(tfChange) forControlEvents:UIControlEventEditingDidEnd];


大致完成了对解析UITableViewCell的reuse问题的分析。