uitableviewcell 重用

UITableView的重用机制


http://www.cnblogs.com/hellocby/archive/2012/05/23/2514469.html

UITableView通过重用单元格来达到节省内存的目的:通过为每个单元格指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,以及当单元格滚出屏幕时,允许恢复单元格以便重用.对于不同种类的单元格使用不同的ID,对于简单的表格,一个标识符就够了.

假如一个TableView中有10个单元格,但是屏幕上最多能显示4个,那么实际上iPhone只是为其分配了4个单元格的内存,没有分配10个,当滚动单元格时,屏幕内显示的单元格重复使用这4个内存,以下代码用于测试内存的使用:

复制代码
 1 - (UITableViewCell *)tableView:(UITableView *)tableView 
 2          cellForRowAtIndexPath:(NSIndexPath *)indexPath
 3 {
 4     UITableViewCellStyle style = UITableViewCellStyleSubtitle;
 5     static NSString *cellID = @"cell";
 6     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
 7     if (cell == nil)
 8     {
 9         cell = [[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:@"cell"] autorelease];
10         cell.detailTextLabel.text = [NSString stringWithFormat:@"Cell %d",++count]; //当分配内存时标记
11     }
12     cell.textLabel.text = [NSString stringWithFormat:@"Cell %d",[indexPath row] + 1];  //当新显示一个Cell时标记
13     return cell;
14 }
复制代码

通过运行此代码 会发现实际上分配的Cell个数为屏幕最大显示数, 当有新的Cell进入屏幕时,会随机调用已经滚出屏幕的Cell所占的内存,这就是Cell的重用







http://hi.baidu.com/306806106/item/e68d099a05e82e8b5814613b

关于uitableviewcell重用cell刷新得解决办法cellForRowAtIndexPath:

通常在创建完UITableViewController后,会看到UITableViewDataSource的一个实现函数如下

- (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 reuseIdentifier:CellIdentifier] autorelease];
}
//config the cell
return cell;
}

而这些代码又是什么意思呢?

每一个UITableView里都维护着一个cell队列,当UITableView刚加载的时候,cell队列里是没有任何数据的。dequeueResableCellWithIdentifier从字面上理解就是”出列可重用的cell",也就是根据一个标识identifier从cell队列里取出一个UITableViewCell,当然了,如果cell队列里没有此标识的cell,调用此方法的结果就是返回nil。因此,在UITableView刚加载的时候,cell队列里没有可用的cell,所以必须通过语句

cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

来创建对应CellIdentifier标识的UITableViewCell实例。

而当UITableView在滚动的时候导致UITableViewCell滚出手机屏幕视图的时候,程序会将这一个UITalbeViewCell实例放入此UITableView所维护的cell队列中。当UITableview中有新的UITableViewCell需要展现在手机屏幕视图上时,就会调用tableView:cellForRowAtIndexPath:方法了,因此我们可以知道以下几点:

1-重取出来的cell是有可能已经捆绑过数据或者加过子视图的,所以,如果有必要,要清除数据(比如textlabel的text)和remove掉add过的子视图(使用tag)。

2-这样设计的目的是为了避免频繁的 alloc和delloc cell对象而已,没有多复杂。

3-设计的关键是实现cell和数据的完全分离

如果不想重用UITableViewCell实例,如在一个每一行都显示不同内容的UITableView实例时,我们可以用如下的方法:

NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d", [indexPath section], [indexPath row]];

来重新定义标识。

这样每一行都有其对应的identifier,从cell队列里取出来只有两个结果:

1-cell队列里没有此identifier对应的UITableViewCell实例,返回nil

2-cell队列里有此identifier对应的UITableViewCell实例,而且不会有重用到其他不同行的cell的情况

--------------------------------------------------------------------------------------------

  将UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:改为

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];







同事指点上一种办法不好,虽然改法简单,但是这浪费内存:


 static NSString *CellIdentifier = @"CustomCellIdentifier";
  //  static BOOL nibsRegistered = NO;
    if (!nibsRegistered) {
        UINib *nib = [UINib nibWithNibName:@"CustomCell" bundle:nil];
        [tableView registerNib:nib forCellReuseIdentifier:CellIdentifier];
        nibsRegistered = YES;
    }
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

定制tablecell要点:


1.首先 registerNib   注册 CellIdentifier
2.然后再用CellIdentifier进行实例化


通过文档,我自己研究了一下,用了两种方法解决了这个问题

1.每次都进委托方法的时候都,clear 一下 UITableViewCell ,代码是

    if (cell!=nil) {

        cell.textLabel.text=nil;

        cell.detailTextLabel.text=nil;

        cell.accessoryView=nil;

    }



2.第二种方法是,用不同的字符串identifier来标记,不同的tableviewcell

   

 //Construct UITableViewCell

    NSString *FormViewSampleTableIdentifier;

    UITableViewCell *cell;


    static NSUInteger editablefalseCountFalse;

    static NSUInteger editablefalseCountTrue;

    if ([editable  isEqualToString:@"false"]) {

    


        FormViewSampleTableIdentifier=@"FormViewSampleTableIdentifierEditableFalse";

        cell=[tableView dequeueReusableCellWithIdentifier:FormViewSampleTableIdentifier];

        if (cell==nil) {

            cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:FormViewSampleTableIdentifier];

            if (textLabel!=nil) {

                cell.textLabel.text=textLabel;

            }

            editablefalseCountFalse++;

            NSLog(@"editablefalseCountFalse:%i",editablefalseCountFalse);

            

        }


        if (value!=nil)

        {

            cell.detailTextLabel.text=value;

        }

    }

    else if([editable isEqualToString:@"true"])

    {

        FormViewSampleTableIdentifier=@"FormViewSampleTableIdentifierEditableTrue";

        if (cell==nil) {

            cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:FormViewSampleTableIdentifier];

            if (textLabel!=nil) {

                cell.textLabel.text=textLabel;

            }

            editablefalseCountTrue++;

            NSLog(@"editablefalseCountTrue:%i",editablefalseCountTrue);

            

        }


        if (value!=nil)

        {

            UITextField *textField=[[UITextField alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 150.0f, 25.0f)];

            textField.borderStyle=UITextBorderStyleRoundedRect;

            textField.text=value;

            textField.delegate=self;

            cell.accessoryView=textField;

//            NSLog(@"indexPath:%@",indexPath);

        }

        

    }

    

    return cell;



上上下下拖动了很久之后,结果如下:2013-05-13 14:07:18.970 Rubic's Cube No StoryBoard[832:14003] editablefalseCountFalse:12013-05-13 14:07:18.974 Rubic's Cube No StoryBoard[832:14003] editablefalseCountFalse:22013-05-13 14:07:20.963 Rubic's Cube No StoryBoard[832:14003] editablefalseCountFalse:32013-05-13 14:07:22.115 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:12013-05-13 14:07:22.182 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:22013-05-13 14:07:25.928 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:32013-05-13 14:07:26.145 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:42013-05-13 14:07:54.060 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:52013-05-13 14:07:54.127 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:62013-05-13 14:08:40.041 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:72013-05-13 14:08:40.141 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:82013-05-13 14:08:40.778 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:92013-05-13 14:09:25.519 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:102013-05-13 14:09:25.762 Rubic's Cube No StoryBoard[832:14003] editablefalseCountTrue:11我分析,editablefalseCountFalse最大是3,说明也没常驻3个,这三个可以重用,但是editablefalseCountTrue就不能重用了,如果页面划到了会一直alloc增加。我把其中一个分支去掉,结果是:2013-05-13 14:35:34.000 Rubic's Cube No StoryBoard[937:14003] applicationDidBecomeActive:2013-05-13 14:35:35.414 Rubic's Cube No StoryBoard[937:14003] editablefalseCountFalse:12013-05-13 14:35:35.417 Rubic's Cube No StoryBoard[937:14003] editablefalseCountFalse:22013-05-13 14:35:36.719 Rubic's Cube No StoryBoard[937:14003] editablefalseCountFalse:3让我试试同事的方法,是怎么样的
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值