本文转载至  http://www.cocoachina.com/bbs/read.php?tid=299773

基本原理是通过缓存每个cell的高度,当tableview回调delegate的heightForRowAtIndexPath的时候,省去了计算cell高度计算,极大的提高了tableview的滑动体验。

因为 heightForRowAtIndexPath这个接口会在reloadData的时候,每个cell都会调用一次,同时滚动tableview的时候,cell从不可见到可见区域也会被调用一次heightForRowAtIndexPath,所以这个API的调用是很频繁的。由于每个cell的高度是动态的,所以每次要做高度计算,都要重新layout一遍,然后得出高度,这块计算量是比较大的。sunny通过将每个cell的计算好的高度缓存起来,下次获取相同位置cell的高度的时候,直接返回缓存的高度。

同时,当第一次reloadData,或者cell的行数发生变化(增减行,section) ,会先在tableview不处于滚动状态的时候异步计算那些没有被计算过的cell的高度,做预缓存,这块非常赞。就是使用者需要小心,由于这块是异步的, tableview delegate有可能会在预缓存计算的时候不存在了,导致程序崩溃,所以使用者在tableview需要析构的时候,在对应的tableview controller的dealloc中讲self.tableview.delegate = nil;,确保delegate后续不会是一个脏对象。

fd_heightForCellWithIdentifier: cacheByIndexPath: configuration: 

  1. 如果没有打开预缓存开关,则打开该开关,然后异步做一遍预缓存行高计算
  2. 如果缓存了改行的高度则返回行高
  3. 如果么有缓存,则计算行高fd_heightForCellWithIdentifier: configuration,缓存行高并返回

fd_heightForCellWithIdentifier: configuration

  1. 首先获取针对这个identifier类型的模板cell,sunny为每一个类型cell都缓存了一个模板cell,这块我还不明白为什么要这么做,为什么不直接用系统dequeue的重用cell来做?
  2. 将需要计算高度的cell数据填充到这个template cell,然后就可以计算cell高度了
  3. 计算tableview.contentView的真实宽度。
    1. 如果有定制accessoryView,则去除这个宽度
    2. 如果有系统accessoryView展示,则去除对应的宽度。
  4. 检查是否是否是自动布局,判断是否自动布局的标准是contentView本身至少存在一个约束。所以我们在CustomCell做约束的时候,需要至少指定contentView的一个约束。
  5. 如果是自动布局,则将contentView的宽度约束添加进去,这样做的目的是让UILabel之类的内容可能多行的控件适应这个宽度折行(当然前提是我们已经设置好了这些控件的布局约束)。然后调用systemLayoutSizeFittingSize来计算高度。最后移除刚才临时添加的contentView宽度约束。
  6. 如果是绝对布局,则custom cell要重写sizeThatFits接口自己提供行高计算。如果没有重写,则会报错。
  7. 如果存在分割线,则添加1px的高度。因为CGSize是基于point,所以高度计算是 1/[UISscreen mainScreen].scale
  8. 返回计算好的高度。

UITableView+FDTemplateLayoutCell源码学习笔记的更多相关文章

  1. Underscore.js 源码学习笔记(下)

    上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...

  2. Underscore.js 源码学习笔记(上)

    版本 Underscore.js 1.9.1 一共 1693 行.注释我就删了,太长了… 整体是一个 (function() {...}());  这样的东西,我们应该知道这是一个 IIFE(立即执行 ...

  3. AXI_LITE源码学习笔记

    AXI_LITE源码学习笔记 1. axi_awready信号的产生 准备接收写地址信号 // Implement axi_awready generation // axi_awready is a ...

  4. Hadoop源码学习笔记(6)——从ls命令一路解剖

    Hadoop源码学习笔记(6) ——从ls命令一路解剖 Hadoop几个模块的程序我们大致有了点了解,现在我们得细看一下这个程序是如何处理命令的. 我们就从原头开始,然后一步步追查. 我们先选中ls命 ...

  5. Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构

    Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构 之前我们简要的看过了DataNode的main函数以及整个类的大至,现在结合前面我们研究的线程和RPC,则可以进一步 ...

  6. Hadoop源码学习笔记(4) ——Socket到RPC调用

    Hadoop源码学习笔记(4) ——Socket到RPC调用 Hadoop是一个分布式程序,分布在多台机器上运行,事必会涉及到网络编程.那这里如何让网络编程变得简单.透明的呢? 网络编程中,首先我们要 ...

  7. Hadoop源码学习笔记(3) ——初览DataNode及学习线程

    Hadoop源码学习笔记(3) ——初览DataNode及学习线程 进入了main函数,我们走出了第一步,接下来看看再怎么走: public class DataNode extends Config ...

  8. Hadoop源码学习笔记(2) ——进入main函数打印包信息

    Hadoop源码学习笔记(2) ——进入main函数打印包信息 找到了main函数,也建立了快速启动的方法,然后我们就进去看一看. 进入NameNode和DataNode的主函数后,发现形式差不多: ...

  9. Hadoop源码学习笔记(1) ——第二季开始——找到Main函数及读一读Configure类

    Hadoop源码学习笔记(1) ——找到Main函数及读一读Configure类 前面在第一季中,我们简单地研究了下Hadoop是什么,怎么用.在这开源的大牛作品的诱惑下,接下来我们要研究一下它是如何 ...

随机推荐

  1. Opengl绘制我们的小屋(二)第一人称漫游

    这章我们先讲第一人称漫游的实现.在openTK里,我们用函数Matrix4.LookAt(caram.Eye,caram.Target,Vector3.UnitY)来放置摄像机,其中三个参数分别与摄像 ...

  2. 嵌入式开发之hi3519---i2c EEPROM

    http://pdf1.alldatasheetcn.com/datasheet-pdf/view/163283/MICROCHIP/24LC024.html http://www.elecfans. ...

  3. Python WSGI开发随笔

    本文记录学习WSGI时的一些知识点,值得后续学习中注意. wsgi应用接口只要是一个可调用的对象就行,这个可调用的对象需要: 1. 接受两个位置参数: a. 包含CGI形式变量的字典: b. 应用调用 ...

  4. CSS :after、before、<!DOCTYPE>

    <!DOCTYPE> <!DOCTYPE> 声明必须是 HTML 文档的第一行,位于 <html> 标签之前. CSS :选择器 after,before

  5. 消息中间件activemq-5.13.0整合spring

    首先说明这里是在qctivemq配置好并启动服务的情况下进行,请先自行配置好.也可关注我的博文(消息中间件qctivemq安全验证配置)进行配置. 1.首先看一下项目结构 2.所需jar包,这里只列出 ...

  6. UITextField禁用掉编辑之后...

    某些UITextField只为了摆数据,还有响应点击,为了避免频繁出现键盘,所以把UITextField的人机交互(userInteractionEnabled)给关闭了 此时,给UITextFiel ...

  7. LR进行接口测试

    其实无论用那种测试方法,接口测试的原理是通过测试程序模拟客户端向服务器发送请求报文,服务器接收请求报文后对相应的报文做出处理然后再把应答报文发送给客户端,客户端接收应答报文这一个过程. 方法一.用Lo ...

  8. Oracle:oratop 第一栏中的 {n}er 的含义,及如何清除这个er

    在oratop监控中: 第一栏的er[不]为{0}!说明Oracle的ADR诊断体系内发现有错误事件(problem + incident) 该信息实际是从一张视图内得来的: select * fro ...

  9. Unity UGUI 的RectTransform参数的设置

    1.改变RectTransform的top GetComponent<RectTransform>().offsetMax = new Vector2(GetComponent<Re ...

  10. 教你下载BarTender 2016

    BarTender是全球领先标签.条形码.RFID和证卡设计打印软件,功能强大,操作简单,具有很强的灵活性.目前,BarTender软件已更新至最新版BarTender 2016.BarTender ...