iOS/Swift:嵌入UITableView的动态UITableView单元格行高不工作

iOS/Swift:嵌入UITableView的动态UITableView单元格行高不工作,ios,swift,uitableview,autolayout,constraints,Ios,Swift,Uitableview,Autolayout,Constraints,我有一个UITableView单元格,它在顶部包含一个UICollectionView,在底部包含一个UITableView。其思想是在内部UITableView中创建动态数量的单元格,并且包含两个子视图的父级UITableViewCell将按比例增加其高度 我试图利用UITableViewCell的estimatedRowHeight+uitableViewAutomaticDeption功能,该功能将允许单元格高度动态增加。然而,它不起作用。它将从视图中完全删除嵌入的UITableView

我有一个
UITableView单元格
,它在顶部包含一个
UICollectionView
,在底部包含一个
UITableView
。其思想是在内部
UITableView
中创建动态数量的单元格,并且包含两个子视图的父级
UITableViewCell
将按比例增加其高度

我试图利用
UITableViewCell
estimatedRowHeight
+
uitableViewAutomaticDeption
功能,该功能将允许单元格高度动态增加。然而,它不起作用。它将从视图中完全删除嵌入的
UITableView

我没有做任何限制附带的
UITableView
高度的限制,因此我不确定它为什么不起作用

以下是尝试创建动态大小的
UITableViewCell
的实现:

class OverviewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "Enclosed Table View Example"
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 3
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 325 // Height for inner table view with 1 cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 45
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let cell = tableView.dequeueReusableCell(withIdentifier: "appHeaderCell") as! AppHeaderCell

        return cell
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "appCell", for: indexPath) as! AppCell

        return cell
    }
}
我唯一的猜测是,约束
bottom=internaltable View.bottom+7
导致了问题,但当删除此约束时,整个视图都会崩溃


如何使复杂的外部
UITableView单元格
根据嵌入的
UITableView
中的单元格数量动态调整高度?

尽管这似乎是个好主意,将
UITableViewAutomaticDimension
EstimatedRowheaight
结合使用,不适合在表视图单元格中包含常规内容的情况下使用。使用
heightForRowAt
方法,可以在每个单元格位于表格中心之前计算其大小

一旦我们知道内部表中有多少个单元格,就需要创建一个数组,其元素对应于最终确定外部单元格高度的内部单元格数量,因为所有其他内容都是常量

let cellListFromData: [CGFloat] = [3, 1, 4]
此数组将提供外部表视图中的节数:

func numberOfSections(in tableView: UITableView) -> Int {
    return cellListFromData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "appCell", for: indexPath) as! AppCell

    cell.numberOfCells = Int(cellListFromData[indexPath.section])
    cell.innerTableView.reloadData()

    return cell
}
我们将按以下方式将此数组中的每个元素转换为单元格高度:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let prototypeCell = tableView.dequeueReusableCell(withIdentifier: "appCell") as! AppCell

    let baseHeight = betweenCellSpacing + prototypeCell.innerCollectionView.contentSize.height + prototypeCell.innerTableView.sectionHeaderHeight + outerTableView.sectionHeaderHeight
    let dynamicHeight = prototypeCell.innerTableView.contentSize.height - prototypeCell.innerTableView.sectionHeaderHeight

    return baseHeight + (dynamicHeight * cellListFromData[indexPath.section])
}
也就是说,在
heightForRowAt
方法中,我们将一个不会在结果视图中使用的原型单元出列(在这种情况下,
dequeueReusableCell
cellForRowAt
中不被调用)。我们使用这个原型单元来提取关于单元内容的常量和动态信息。
baseHeight
是单元格中所有常量元素的累计高度(加上单元格之间的间距),
dynamicHeight
是内部
UITableViewCell
的高度。然后每个单元格的高度变为
baseHeight+dynamicHeight*cellListFromData[indexPath.section]

接下来,我们为自定义单元格的类添加一个
numberOfCells
变量,并在主表视图中的
cellForRowAt
方法中进行设置:

func numberOfSections(in tableView: UITableView) -> Int {
    return cellListFromData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "appCell", for: indexPath) as! AppCell

    cell.numberOfCells = Int(cellListFromData[indexPath.section])
    cell.innerTableView.reloadData()

    return cell
}
numberOfCells
使用与我们用于获取单元格高度的相同的
cellListFromData
设置。此外,在设置内部表视图的单元格数后,在该视图上调用
reloadData()
,以便在UI中看到该更新,这一点非常重要

以下是完整的代码:

class OverviewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var outerTableView: UITableView!
    let cellSpacing: CGFloat = 25
    let data: [CGFloat] = [3, 1, 4]

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return data.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        let prototypeCell = tableView.dequeueReusableCell(withIdentifier: "appCell") as! AppCell

        let baseHeight = cellSpacing + prototypeCell.innerCollectionView.contentSize.height + prototypeCell.innerTableView.sectionHeaderHeight + outerTableView.sectionHeaderHeight
        let dynamicHeight = prototypeCell.innerTableView.contentSize.height - prototypeCell.innerTableView.sectionHeaderHeight

        return baseHeight + (dynamicHeight * data[indexPath.section])
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "appCell", for: indexPath) as! AppCell

        cell.numberOfCells = Int(data[indexPath.section])
        cell.innerTableView.reloadData()

        return cell
    }
}

class AppCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var innerCollectionView: UICollectionView!
    @IBOutlet weak var innerTableView: UITableView!
    var numberOfCells: Int = 0

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return numberOfCells
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let cell = tableView.dequeueReusableCell(withIdentifier: "featureHeaderCell") as! BuildHeaderCell

        return cell
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "innerCell", for: indexPath) as! InnerCell

        return cell
    }
}
此处不包括与配置内部集合视图相关的方法,因为它与问题无关