zoukankan      html  css  js  c++  java
  • IOS之TableViewCell重用机制解决上下刷新重复显示

    首先我是一个经验浅薄的iOS开发人员,这个问题想必许多初学者经常遇到这些问题,在面试中也会经常问到。现在我们一一解决。

    1. 首先我们要知道TableViewCell重用机制的原理是什么,我们抽象的理解为古代的水车(圆的那种),屏幕可以显示出来的区域就是水车的右半部分。不需要重复创建新的,而是重用已经从页面消失的那部分。
    2. 我们跟踪UITableView进入头文件,会找到NSMutableArray*  visiableCells,和NSMutableDictnery* reusableTableCells两个结构。visiableCells内保存当前显示的cells,reusableTableCells保存可重用的cells。TableView显示之初,reusableTableCells为空,那么tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。开始的cell都是通过[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]来创建,而且cellForRowAtIndexPath只是调用最大显示cell数的次数。

      比如:有100条数据,iPhone一屏最多显示10个cell。程序最开始显示TableView的情况是:

      1. 用[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]创建10次cell,并给cell指定同样的重用标识(当然,可以为不同显示类型的cell指定不同的标识)。并且10个cell全部都加入到visiableCells数组,reusableTableCells为空。

      2. 向下拖动tableView,当cell1完全移出屏幕,并且cell11(它也是alloc出来的,原因同上)完全显示出来的时候。cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。

      3. 接着向下拖动tableView,因为reusableTableCells中已经有值,所以,当需要显示新的cell,cellForRowAtIndexPath再次被调用的时候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出visiableCells,cell2加入到reusableTableCells。之后再需要显示的Cell就可以正常重用了。

      所以整个过程并不难理解,但需要注意正是因为这样的原因:配置Cell的时候一定要注意,对取出的重用的cell做重新赋值,不要遗留老数据。看完这个应该对tableViewCell重用机制有所理解吧。多说无益,我们上代码。

    1. 取消cell的重用机制,通过indexPath来创建cell 将可以解决重复显示问题 不过这样做相对于大数据来说内存就比较吃紧了
      // 方案一  通过不让他重用cell 来解决重复显示
      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
      {
          // 定义唯一标识
          static NSString *CellIdentifier = @"Cell";
          // 通过indexPath创建cell实例 每一个cell都是单独的
          UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
          // 判断为空进行初始化  --(当拉动页面显示超过主页面内容的时候就会重用之前的cell,而不会再次初始化)
          if (!cell) {
              cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
          }
          // 对cell 进行简单地数据配置
          cell.textLabel.text = @"text";
          cell.detailTextLabel.text = @"text";
          cell.imageView.image = [UIImage imageNamed:@"4.png"];
          
          return cell;
      }

    方案二  让每个cell都拥有一个对应的标识 这样做也会让cell无法重用 所以也就不会是重复显示了 显示内容比较多时内存占用也是比较多的和方案一类似 

    // 方案二  同样通过不让他重用cell 来解决重复显示 不同的是每个cell对应一个标识
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // 定义cell标识  每个cell对应一个自己的标识
        NSString *CellIdentifier = [NSString stringWithFormat:@"cell%ld%ld",indexPath.section,indexPath.row];
        // 通过不同标识创建cell实例
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        // 判断为空进行初始化  --(当拉动页面显示超过主页面内容的时候就会重用之前的cell,而不会再次初始化)
        if (!cell) {
            cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        }
        // 对cell 进行简单地数据配置
        cell.textLabel.text = @"text";
        cell.detailTextLabel.text = @"text";
        cell.imageView.image = [UIImage imageNamed:@"4.png"];
        
        return cell;
    } 

    希望能够对大家起到一定的帮助!! 如有更好的思路请多多指出。Thank you!

     

  • 相关阅读:
    练习二(米奇老鼠)
    Photoshop笔记一
    HTML笔记1
    用IDEA写出第一个java web
    TCP协议怎么关闭?
    Sql Server2008R2与IDEA的连接
    通过HttpServer向Prometheus暴露端点
    了解Prometheus到底是什么?
    SPI扩展机制在框架中的使用
    motan系列1——与spring的集成原理
  • 原文地址:https://www.cnblogs.com/YRFios/p/6393606.html
Copyright © 2011-2022 走看看