关于UITableViewCell的复用

这个问题一直困扰着我,都醉了,网上很多例子,都是用最简单的例子告诉你怎么做,但一遇到复杂的,大型的问题,也就玩了。

所以这里我由简单到复杂讲讲复用这件事情吧。


因为都是经验之谈,可能有说的不到位的,还请指正。


我们在使用UITableView的时候,都会用UITableViewCell来显示一条条的数据。假如我们在一屏上显示6条数据,那么大概至少需要创建6个UITableViewCell,这个是必须的。

但往往我们要显示的数据会超过6条。例如新浪微博,只要一直往下拉,数据源源不断,那么正常情况情况下,显示多少条数据,就要创建多少条UITableViewCell及上面的子视图,想象一下,手机的CPU是不是很容易晕倒,嘿嘿,开个玩笑。反正这样做是十分浪费资源的一件事情。那么怎么办呢。于是乎聪明的编程员想了好的办法---------------复用。


好高端的词语啊,第一次听说,我就晕倒了,哈哈哈!


所谓复用,即重复使用,这个词语是针对UITableViewCell,所以又叫重复使用cell。


上面我们讲了UITableViewCell的正常用法,下面就是复用情况下UITableViewCell的思路。继续说那个创建的6个UITableViewCell事,正常情况下要显示多条数据,那么要创建多个UITableViewCell,在复用的情况下,我们不要创建那么多,只需要创建大概7个UITableViewCell,具体的,你自己测试一下吧。当我们往上拖动UITableView的时候,第一个cell消失,创建第7个cell,系统并不把第1个cell销毁,而是再次往下滑动时,复用第一个cell,充当第8个cell,这样显示第8个cell,如此下来,只需要创建(屏幕上显示的cell个数+1)个cell,节省了系统资源。此种方法即为复用。


以上所讲均为苹果的程序猿想的关于UITableViewCell重复创建而引起的内存浪费的问题的解决方案。


我们在使用的时候,情况往往是很复杂的。系统的几种类型的cell往往不能完全符合我们的需求,则需要我们定制cell,或者添加多个label、imageView,这种情况下我们应该如何真正的利用上复用呢。


先讲一中错误的例子。


    static NSString *cellIdentifier = @"cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    

    if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    }

    

    UILabel *lbl1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 160, 46)];

    lbl1.textAlignment = NSTextAlignmentCenter;

    lbl1.text = [NSString stringWithFormat:@":%ld",(long)indexPath.row];

    [cell.contentView addSubview:lbl1];

    

    UILabel *lbl2 = [[UILabel alloc] initWithFrame:CGRectMake(160, 0, 160, 46)];

    lbl2.textAlignment = NSTextAlignmentCenter;

    lbl2.text = [NSString stringWithFormat:@":%ld",(long)indexPath.row];

    [cell.contentView addSubview:lbl2];

    

    return cell;


如果你只这么写,恭喜你,tableView的显示效果肯定会是很多重叠,反正是不对的。


然后又有人这样写


    static NSString *cellIdentifier = @"cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];


   NSArray *views = [cell.contentView subviews];

    for (id tmp in views) {

        [tmp removeFromSuperview];

    }


    if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    }

    

    UILabel *lbl1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 160, 46)];

    lbl1.textAlignment = NSTextAlignmentCenter;

    lbl1.text = [NSString stringWithFormat:@":%ld",(long)indexPath.row];

    [cell.contentView addSubview:lbl1];

    

    UILabel *lbl2 = [[UILabel alloc] initWithFrame:CGRectMake(160, 0, 160, 46)];

    lbl2.textAlignment = NSTextAlignmentCenter;

    lbl2.text = [NSString stringWithFormat:@":%ld",(long)indexPath.row];

    [cell.contentView addSubview:lbl2];

    

    return cell;

这样写确实解决了数据覆盖的问题,你的数据可以正常的显示了,可是如果数据非常多而手机的性能又较低的情况下,你的手机肯定会有内存警告。根据上面讲的复用的方法,你有没有感觉到哪里出了问题。


问题就是你一直创建label然后又移除,这种状况就像没有使用复用情况下的cell的创建,又是在浪费手机的CPU啊。


那该怎么办呢????????????此处才是正解。


static NSString *cellIdentifier = @"cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    

    if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

        

        UILabel *lbl1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 160, 46)];

        lbl1.tag = 10001;

        lbl1.textAlignment = NSTextAlignmentCenter;

        [cell.contentView addSubview:lbl1];

        

        UILabel *lbl2 = [[UILabel alloc] initWithFrame:CGRectMake(160, 0, 160, 46)];

        lbl2.tag = 10002;

        lbl2.textAlignment = NSTextAlignmentCenter;

        [cell.contentView addSubview:lbl2];

    }

    

    UILabel *lbl1 = (UILabel *)[cell.contentView viewWithTag:10001];

    lbl1.text = [NSString stringWithFormat:@":%ld",(long)indexPath.row];

    UILabel *lbl2 = (UILabel *)[cell.contentView viewWithTag:10002];

    lbl2.text = [NSString stringWithFormat:@":%ld",(long)indexPath.row];


    return cell;


你会发现这种情况下不会重叠。而且label只有在创建cell的时候创建,也就是假如这个一屏显示6个cell的情况,那么需要创建7个cell,和上面对应的7个lbl1和7个lbl2,以后只需要获取使用即可(讲到这里你不明白的话,查查tag的用法,或者在好好想想)。


所以上面就是cell复用的基本用法。然后又出现问题了,有装逼的人问了,如果我创建的cell中一行显示label,一行显示imageview怎么办,这往往出现在

面试中。那就需要初始化俩种类型的cell。


    static NSString *cellIdentifierlabel = @"cellLabel";

    static NSString *cellIdentifierimageView = @"cellImageView";

    UITableViewCell *cell;

    if(indexPath.row%2 == 0){

        cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifierlabel];

        if (cell == nil) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifierlabel];

            

            UILabel *lbl1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 160, 46)];

            lbl1.tag = 10001;

            lbl1.textAlignment = NSTextAlignmentCenter;

            [cell.contentView addSubview:lbl1];

            

            UILabel *lbl2 = [[UILabel alloc] initWithFrame:CGRectMake(160, 0, 160, 46)];

            lbl2.tag = 10002;

            lbl2.textAlignment = NSTextAlignmentCenter;

            [cell.contentView addSubview:lbl2];

        }

    }else{

        cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifierimageView];

        if (cell == nil) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifierimageView];

            UIImageView *img1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 160, 46)];

            img1.tag = 10003;

            [cell.contentView addSubview:img1];

            

            UIImageView *img2 = [[UIImageView alloc] initWithFrame:CGRectMake(160, 0, 160, 46)];

            img2.tag = 10003;

            [cell.contentView addSubview:img2];

        }

    }

    if (indexPath.row%2 == 0) {

        UILabel *lbl1 = (UILabel *)[cell.contentView viewWithTag:10001];

        lbl1.text = [NSString stringWithFormat:@":%ld",(long)indexPath.row];

        UILabel *lbl2 = (UILabel *)[cell.contentView viewWithTag:10002];

        lbl2.text = [NSString stringWithFormat:@":%ld",(long)indexPath.row];

    }else{

        UIImageView *img1 = (UIImageView *)[cell.contentView viewWithTag:10003];

        img1.image = [UIImage imageNamed:@"1.jpg"];

        

        UIImageView *img2 = (UIImageView *)[cell.contentView viewWithTag:10004];

        img2.image = [UIImage imageNamed:@"2.jpg"];

    }

    return cell;


这个代码的意义在于何处呢??????


就是在显示cell的过程中,你需要创建俩种类型的cell,然后需要俩个不同的cellIndetifier,可以区分俩种cell。


如上已经把cell的复用讲完了,还有什么问题,留言啥的交流吧!



好吧!回头又看这篇文章,觉得缺点什么--------------------------------------------------------------------

以上所说的是全部代码去构建的程序,目的是让你完全理解什么是复用,正确地运用复用原理。

实际开发中,往往有另外一种方式,即自定义cell。这是一种极其简单的方式,简单到你只需要重新创建一个类,该类继承UITableViewCell,并且按照自己的期望拖拖控件,然后在使用的时候使用定义的类,具体的,我就不说了。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值