【问题标题】:Force UITableView to cache reusable cells强制 UITableView 缓存可重用单元格
【发布时间】:2012-06-06 16:57:31
【问题描述】:

我使用具有相对“重”的自定义表格视图单元格的表格视图 - 假设单个单元格中有大约 100 个子视图(完整层次结构)。尽管如此,我已经能够实现非常平滑的滚动 - 使用标准做法,例如仅使用不透明视图、隐藏未使用的子视图(甚至从视图层次结构中删除)、预加载单元格高度等。

问题在于创建单个单元格实例的成本仍然相对较高。由于标准 UITableView 的单元格重用逻辑的工作原理,这个问题仅在特定条件下才会引起注意。

通常在加载表格视图(并显示初始内容)时,它会创建几乎所有必需的单元格实例 - 因此,当您开始滚动时,它很少需要创建更多可重用的单元格。但是,如果由于某种原因它只在开始时显示几个单元格,那么在启动滚动时显然需要创建更多单元格。在我的情况下,如果有一个宽表视图标题或第一个单元格足够大,这很明显。当您开始滚动时发生这种情况时,会有片刻的明显滞后,这显然是由创建的新单元格实例引起的。没有什么丑陋但仍然很明显,尤其是与之后的绝对平滑滚动相比。

现在,显而易见的解决方案是让单元格“更轻”——比如将它们分成不同的更具体的类型,这样每个单元格就可以包含更少的子视图。但由于我的内容的组织方式,这将是一个非常复杂的解决方案。

所以我的问题是 - 有没有什么好方法可以“欺骗”表格视图逻辑以立即强制加载和缓存特定数量的可重用单元格实例 - 尽管实际可见的单元格数量是多少?

我一直在考虑的选项之一是拥有自己的显式单元缓存,并在需要时用单元预填充它(比如在 -viewDidLoad 中)。这种方法的问题是你必须事先知道你需要的确切类型的细胞——对我来说效果不佳。改进是在加载初始数据时构建缓存(因此至少知道内容的确切类型),但我一直想知道是否有任何简单的选项。

【问题讨论】:

    标签: ios uitableview


    【解决方案1】:

    您可以通过将自己的“二级缓存”层添加到数据源来实现。

    初始化数据源时,根据需要预先创建尽可能多的单元格,并将它们放入数组中。当你的dequeueReusableCellWithIdentifier 失败时,先去那个数组,然后从那里取一个单元格。一旦阵列用尽,开始创建新的单元格(如果您预先创建了足够多的单元格,则不需要即时创建新的单元格:当您有足够多的单元格在可见性范围内旋转时,出队最终将停止失败)。

    【讨论】:

      【解决方案2】:

      我也有类似的情况,我想在不同的单元格中加载几个网站,并且 loadrequest 必须只触发一次。想法是在通过向上或向下滚动使单元格可见/不可见时避免重复调用。假设我的表格视图中有 5 个单元格,每个单元格都有一个加载不同网站的 web 视图。 loadrequest 将被调用一次,单元格将被缓存。这是最简单的实现。

      变量声明

      let weblinks:[String] = ["http://www.google.com",
                               "http://www.facebook.com",
                               "http://www.yahoo.com",
                               "http://www.puthiyathalaimurai.com/",
                               "http://www.github.com"]
      var mycells:[MyTableViewCell] = [MyTableViewCell(),
                                       MyTableViewCell(),
                                       MyTableViewCell(),
                                       MyTableViewCell(),
                                       MyTableViewCell()]
      

      CellForRow。我希望你知道它的作用,

      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          let cellIdentifier = String(describing: MyTableViewCell.self)
      
          let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as? MyTableViewCell
          if cell?.isNewCell == true { //return from cache
              return mycells[indexPath.row]
          }
          cell?.title.text = weblinks[indexPath.row].uppercased()
          cell?.web.loadRequest(URLRequest(url: URL(string: weblinks[indexPath.row])!))
          cell?.isNewCell = true //mark it for cache
          mycells[indexPath.row] = cell!
          return cell!
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-18
        • 2016-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多