浅析UITableViewCell重用机制

本文深入分析了UITableView的Cell重用机制,包括单一类型Cell和多种类型Cell的情况,并探讨了因重用导致的图片错位问题及解决方案。通过案例展示了两种获取重用Cell的方法,强调了在配置Cell时确保清除遗留数据的重要性。
摘要由CSDN通过智能技术生成

欢迎访问本人独立博客:http://sharonhu1990.github.io/
UITableView在iOS开发中用的非常的多,由于Cell中一般都会有Image等占用内存的资源,容易引起Memory Warning,所以iOS引入了重用机制。那么今天就对UITableView的重用机制分析一下。

案例分析

情况A:所有Cell具有相同的类型

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSInteger times = 0;
        static NSString *cellIdentifier = @"Default Type";
        UITableViewCell *myCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (myCell == nil) {
            myCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
            NSLog(@"创建%d次",++times);
        }
        myCell.textLabel.text= [NSString stringWithFormat:@"第%d行 %@",indexPath.row+1, cellIdentifier];
        return myCell;
    }

分析:

  • 有两个存放Cell的队列:可复用Cell队列 reusableCellQueue 和可见的Cell队列 visualCellQueue
  • 执行cellForRowAtIndexPath之前,先从reusableCellQueue中寻找标识为Default Style的Cell,如果没有,返回nil,接着会执行initWithStyle:reuseIdentifier
  • 假设屏幕显示 11行 Cell,如果不滚动TableView,reusableCellQueue是空的,Cell被创建了11次;
  • 向上拖动TableView,使第12行Cell出现在屏幕中(加入到visualCellQueue中),这时,reusableCellQueue仍然是空的。所以又创建了一次Cell;
  • 当第12行Cell完全出现在visualCellQueue中,第1行Cell就加入到了reusableCellQueue中。
  • 再次向上拖动TableView,使第13行Cell出现。注意,这时从reusableCellQueue中寻找到了标识为Default Style的Cell,于是第一行Cell被复用,不用重新创建Cell。
  • 以后再上下滑动,都会在reusableCellQueue中找到可复用的Cell,因此,此TableView完成完整的滚动需要创建 12次 Cell。
  • 总结:第一页显示N行Cell,则一共创建了N+1次。

情况B:具有多种类型的Cell

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *cellIdentifier;
        UITableViewCellStyle cellStyle;
        switch ((indexPath.row + 1)%4) {
            case 1:{
                //有标题和副标题,可选图片
                cellIdentifier = @"Subtitle Style";
                cellStyle = UITableViewCellStyleSubtitle;
            }
                break;
            case 2:{
                //左边文字左对齐,右边文字右对齐,可选的图片
                cellIdentifier = @"Value1 Style";
                cellStyle = UITableViewCellStyleValue1;
            }
                break;
            case 3:{
                //左边文字右对齐,蓝色字体。右边文字左对齐,黑色。没有图片
                cellIdentifier = @"Value2 Style";
                cellStyle = UITableViewCellStyleValue2;
            }
                break;
            default:{
                //有标题,没有副标题,可选的图片
                cellIdentifier = @"Default Style";
                cellStyle = UITableViewCellStyleDefault;
            }
                break;
        }

        static NSInteger times = 0;
        UITableViewCell *myCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (!myCell) {
            myCell = [[UITableViewCell alloc] initWithStyle:cellStyle reuseIdentifier:cellIdentifier];
            NSLog(@"创建%d次",++times);
        }
        myCell.textLabel.text = [NSString stringWithFormat:@"第%d行%@",indexPath.row+1, cellIdentifier];
        myCell.detailTextLabel.text = @"Subtitle Text";
        if (indexPath.row > 3) {
            myCell.imageView.image = [UIImage imageNamed:@"smile.png"];
        }
        return myCell;
    }

运行结果是这样的:
不同ReusableCellIdentifier的Cell

分析:

  • 第一页显示11个Cell,创建了11次。
  • 向上拖动TableView,使第12行Cell出现,第12行是Default Style类型的,可复用队列为空,没有找到可复用Cell,于是又创建一次(第12次)。第一个Cell进入reusableCellQueue中。此时reusableCellQueue中只有一个Subtitle Style的Cell。
  • 再次向上拖动,当第13个Cell出现时,从reusableCellQueue中寻找标识为Subtitle Style的Cell,Yes,reusableCellQueue里有这个标识的Cell,于是复用队列里的这个Cell。此时第二个Cell进入reusableCellQueue,队列里有这几个标识:Subtitle StyleValue1 Style
  • 当第14个Cell出现时,寻找标识为Value1 Style的Cell,也找到了,复用之。此时队列里有Subtitle StyleValue1 StyleValue2 Style
  • 以此类推,以后的Cell都可以在reusableCellQueue中找到可复用的Cell。因此一共创建了12次Cell。

不该有图片的Cell出现了图片

当上下滑动TableView的时候,会出现第一行的Cell一会有图片,一会儿又没有图片的现象。这是为什么呢?

第一个Cell应该是没有图片的,但是在TableView向下滚动,使第一个Cell出现在屏幕上的时候,会先从reusableCellQueue中寻找标识为Subtitle Style的Cell。注意了,第5、9、13、17行的Cell都是Subtitle Style类型的,而且还都带有图片,因此,当这些类型的Cell在reusableCellQueue中被寻找到时,第一行Cell上就会出现图片。

那么,如何解决这类问题呢?

在配置Cell的时候一定要注意,对取出的重用的cell要重新赋值,不能遗留被重用Cell的数据。

区分两个获取重用Cell的方法

- dequeueReusableCellWithIdentifier:forIndexPath:

此方法返回一个相关标识的UITableViewCell对象,这个Cell总是有效的(不是nil)。

* 注意:*
使用这个方法之前,必须使用registerNib:forCellReuseIdentifier:或者registerClass:forCellReuseIdentifier:注册一个Cell类或者nib。

    [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellIdentifier];
        UITableViewCell *myCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

- dequeueReusableCellWithIdentifier:

返回值 : 相关标识的UITableViewCell对象,或者是nil(如果在可重用Cell队列中没有找到的话)。

       UITableViewCell *myCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (myCell == nil) {
        myCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }

比较

使用- dequeueReusableCellWithIdentifier:forIndexPath:的话,必须注册Cell,而且,不需要再判断Cell是否为nil和创建 Cell。

在使用 `UICollectionView` 或 `UITableView` 时,由于重用机制,可能会导致数据错乱的问题。这是因为当滚动视图滚动时,会将离开屏幕的 `UICollectionViewCell` 或 `UITableViewCell` 放入重用池中,然后再从重用池中取出一个可用的 cell 来显示新的数据,如果没有正确地处理这个过程,就会导致数据错乱的问题。 解决这个问题的方法有多种,下面列举几种常用的方法: 1. 在 `cellForItemAt` 或 `cellForRowAtIndex` 方法中,一定要确保对 cell 的每个子视图进行初始化或设置。例如,设置 label 的文本、image view 的图片等。 2. 在 cell 的 `prepareForReuse` 方法中,清空 cell 中的数据,以便重用时重新设置新的数据。 3. 使用自定义的 cell,而不是系统的默认 cell。在自定义 cell 中,可以更加精细地控制 cell 中的子视图,避免出现数据错乱的问题。 4. 在数据源数组中保存每个 cell 的状态,包括 cell 中每个子视图的状态。在 `cellForItemAt` 或 `cellForRowAtIndex` 方法中,根据数据源数组中保存的状态来设置 cell 的状态,避免出现数据错乱的问题。 5. 使用 `UICollectionViewFlowLayout` 或 `UITableViewFlowLayout` 来实现布局,而不是手动计算 cell 的位置。这样可以避免手动计算 cell 的位置时出现的误差,从而减少数据错乱的问题。 以上是一些常用的解决方法,具体的解决方法还需要根据具体的情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值