UITableView(QMUILayoutCell)

@interface UITableView (QMUILayoutCell)

UITableView 定义了一套动态计算 cell 高度的方式:

其思路是参考开源代码:https://github.com/forkingdog/UITableView-FDTemplateLayoutCell。

  1. cell 必须实现 sizeThatFits: 方法,在里面计算自身的高度并返回
  2. 初始化一个 QMUITableView,并为其指定一个 QMUITableViewDataSource
  3. 实现 qmui_tableView:cellWithIdentifier: 方法,在里面为不同的 identifier 创建不同的 cell 实例
  4. 在 tableView:cellForRowAtIndexPath: 里使用 qmui_tableView:cellWithIdentifier: 获取 cell
  5. 在 tableView:heightForRowAtIndexPath: 里使用 UITableView (QMUILayoutCell) 提供的几种方法得到 cell 的高度
  6. 当某个 cell 的缓存需要主动刷新时,请调用 UITableView 的 qmui_invalidateXxx 系列方法。

这套方式的好处是 tableView 能直接操作 cell 的实例,cell 无需增加额外的专门用于获取 cell 高度的方法。并且这套方式支持基本的高度缓存(可按 key 缓存或按 indexPath 缓存),若使用了缓存,请注意在适当的时机去更新缓存(例如某个 cell 的内容发生变化,可能 cell 的高度也会变化,则需要更新这个 cell 已被缓存起来的高度)。

使用这套方式额外的消耗是每个 identifier 都会生成一个多余的 cell 实例(专用于高度计算),但大部分情况下一个生成一个 cell 实例并不会带来过多的负担,所以一般不用担心这个问题。

Note

当 tableView 的宽度发生变化时,缓存会自动刷新,所以无需自己监听横竖屏旋转、viewWillTransitionToSize: 等事件。

Note

注意,如果你的 tableView 可以使用 estimatedRowHeight,则建议使用 UITableView (QMUICellHeightKeyCache) 代替本控件,可节省大量代码。

See

UITableView (QMUICellHeightKeyCache)

  • 通过 qmui_tableView:cellWithIdentifier: 得到 identifier 对应的 cell 实例,并在 configuration 里对 cell 进行渲染后,得到 cell 的高度。

    Declaration

    Objective-C

    - (CGFloat)qmui_heightForCellWithIdentifier:(NSString *)identifier
                                  configuration:
                                      (void (^)(__kindof UITableViewCell *))
                                          configuration;

    Swift

    func qmui_heightForCell(withIdentifier identifier: String!, configuration: ((UITableViewCell?) -> Void)!) -> CGFloat

    Parameters

    identifier

    cell 的 identifier

    configuration

    用于渲染 cell 的block,一般与 tableView:cellForRowAtIndexPath: 里渲染 cell 的代码一样

  • 通过 qmui_tableView:cellWithIdentifier: 得到 identifier 对应的 cell 实例,并在 configuration 里对 cell 进行渲染后,得到 cell 的高度。

    以 indexPath 为单位进行缓存,相同的 indexPath 高度将不会重复计算,若需刷新高度,请参考 QMUICellHeightIndexPathCache

    Declaration

    Objective-C

    - (CGFloat)qmui_heightForCellWithIdentifier:(NSString *)identifier
                               cacheByIndexPath:(NSIndexPath *)indexPath
                                  configuration:
                                      (void (^)(__kindof UITableViewCell *))
                                          configuration;

    Swift

    func qmui_heightForCell(withIdentifier identifier: String!, cacheBy indexPath: IndexPath!, configuration: ((UITableViewCell?) -> Void)!) -> CGFloat

    Parameters

    identifier

    cell 的 identifier

    configuration

    用于渲染 cell 的block,一般与 tableView:cellForRowAtIndexPath: 里渲染 cell 的代码一样

  • 通过 qmui_tableView:cellWithIdentifier: 得到 identifier 对应的 cell 实例,并在 configuration 里对 cell 进行渲染后,得到 cell 的高度。

    以自定义的 key 为单位进行缓存,相同的 key 高度将不会重复计算,若需刷新高度,请参考 QMUICellHeightCache

    Declaration

    Objective-C

    - (CGFloat)qmui_heightForCellWithIdentifier:(NSString *)identifier
                                     cacheByKey:(id<NSCopying>)key
                                  configuration:
                                      (void (^)(__kindof UITableViewCell *))
                                          configuration;

    Swift

    func qmui_heightForCell(withIdentifier identifier: String!, cacheByKey key: NSCopying!, configuration: ((UITableViewCell?) -> Void)!) -> CGFloat

    Parameters

    identifier

    cell 的 identifier

    configuration

    用于渲染 cell 的block,一般与 tableView:cellForRowAtIndexPath: 里渲染 cell 的代码一样

  • 搭配 QMUICellHeightCache,清除整个列表的所有高度缓存(包括 key 和 indexPath),注意请不要直接使用 self.qmui_keyedHeightCache 或 self.qmui_indexPathHeightCache 的 invalidate 方法,因为一个 UITableView 在不同宽度下会有不同的 QMUICellHeightCache/QMUICellHeightIndexPathCache,直接使用那两个 cache 的 invalidate 方法只能刷新当前的 cache,无法刷新其他宽度下的 cache。

    Declaration

    Objective-C

    - (void)qmui_invalidateAllHeight;

    Swift

    func qmui_invalidateAllHeight()