You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套UITableViewCell的UITableView动态行高实现难题

嘿,这个场景我太熟了——嵌套TableView动态调整行高,核心就是要让外层的master tableView能精准拿到内层child tableView的真实内容高度,然后实时更新自身cell的高度。下面给你一步步拆解解决方案:

核心思路

问题的关键在于:master tableView初始化时,child tableView可能还没加载完数据,导致无法拿到真实高度。我们需要做的是在child tableView数据就绪后,把它的内容高度传递给master tableView,触发master tableView重新计算对应cell的行高。

1. 给嵌套Child TableView的自定义Cell添加高度回调

首先在你的自定义Cell(包含child tableView的那个)里,定义一个闭包用来传递高度。同时要禁用child tableView的滚动,确保它的内容全部展开,这样contentSize才能准确反映总高度:

class ChildContainerCell: UITableViewCell {
    @IBOutlet weak var childTableView: UITableView!
    // 用来传递child tableView内容高度的闭包
    var contentHeightUpdated: ((CGFloat) -> Void)?
    private var childData: [YourDataModel] = []
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // 配置child tableView的数据源/代理(这里假设Cell自身担任代理)
        childTableView.dataSource = self
        childTableView.delegate = self
        // 关键设置:禁用滚动,让内容全部展开
        childTableView.isScrollEnabled = false
        childTableView.showsVerticalScrollIndicator = false
        // 如果child tableView是动态行高,必须设置预估高度
        childTableView.rowHeight = UITableView.automaticDimension
        childTableView.estimatedRowHeight = 44
    }
    
    // 外部调用这个方法给child tableView传数据
    func setup(with data: [YourDataModel]) {
        self.childData = data
        childTableView.reloadData()
        // 数据加载完成后,计算并传递真实高度
        let realHeight = childTableView.contentSize.height
        contentHeightUpdated?(realHeight)
    }
}

// 实现child tableView的数据源方法
extension ChildContainerCell: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return childData.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ChildCell", for: indexPath) as! ChildCell
        cell.setup(with: childData[indexPath.row])
        return cell
    }
}

2. 在Master ViewController中处理高度更新

在master tableView的cellForRowAt方法里,绑定Cell的高度回调,把得到的真实高度存储起来,然后触发master tableView更新对应行的高度:

class MasterVC: UITableViewController {
    // 存储每个Cell的真实高度,用row作为key
    private var cellHeightCache: [Int: CGFloat] = [:]
    private var masterData: [[YourDataModel]] = [] // 外层数据源,每个元素对应一个child tableView的数据
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ChildContainerCell", for: indexPath) as! ChildContainerCell
        
        // 给Cell传递对应的数据
        let childData = masterData[indexPath.row]
        cell.setup(with: childData)
        
        // 绑定高度回调
        cell.contentHeightUpdated = { [weak self] height in
            guard let self = self else { return }
            // 缓存当前Cell的真实高度
            self.cellHeightCache[indexPath.row] = height
            // 触发master tableView重新计算行高
            self.tableView.beginUpdates()
            self.tableView.endUpdates()
        }
        
        return cell
    }
    
    // 告诉master tableView每行的高度:优先用缓存的真实高度,没有则用预估高度
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return cellHeightCache[indexPath.row] ?? 200 // 200是你xib的原始高度,作为预估值
    }
    
    override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return cellHeightCache[indexPath.row] ?? 200
    }
}

3. 解决初始化时的时机问题

上面的方案已经覆盖了初始化场景:当master tableView首次加载Cell时,调用setup(with:)会触发child tableView reloadData,随后计算真实高度并通过回调通知master tableView更新行高。即使初始时master用了预估高度,等child数据就绪后会自动调整到真实高度。

额外注意事项

  • 如果child tableView的内容会动态变化(比如新增/删除行),要在内容变更后重新计算高度并触发contentHeightUpdated回调。
  • 如果child tableView是固定行高,也可以直接提前计算高度(行数×行高+内边距),不用依赖contentSize,这样初始化时就能直接拿到准确高度:
// 在ChildContainerCell的setup方法里替换高度计算逻辑
let fixedRowHeight: CGFloat = 44
let realHeight = CGFloat(childData.count) * fixedRowHeight + childTableView.contentInset.top + childTableView.contentInset.bottom
contentHeightUpdated?(realHeight)

内容的提问来源于stack exchange,提问作者knart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:26:12