如何动态设置tableView高度?

时间:2021-07-08 13:11:25

标签: ios swift uitableview

我很难根据它的内容设置我的 tableView 高度。我的单元格具有动态高度,如果我为表格视图硬编码高度,我可以看到它们很好。现在我的问题是:

  • 我的表格视图没有根据我的单元格调整到正确的高度

  • 如果我没有为表格视图设置静态高度,单元格不会被渲染

  • 奖励问题:我使用 SnapKit 来制作约束,当我根据内容大小重新制作约束以适应我的表格视图高度时,它触发 viewDidLoad 次与单元格一样多*

这里所说的都是一些代码:

class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    private var cellHeight: CGFloat? = UITableView.automaticDimension
    private var hasLoader: Bool = true
    lazy var tableView: UITableView! = UITableView()
    lazy var loadMoreButton: UIButton! = PrimaryButton(textKey: "actionSeeMore")
    lazy var emptyView: UILabel! = UILabel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(Cell.self, forCellReuseIdentifier: "Cell")
        tableView.dataSource = self
        tableView.delegate = self
        tableView.separatorStyle = .none
        tableView.rowHeight = UITableView.automaticDimension
        initActions()
        initLayout()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        loadList(appendItems: true)
    }

    func initLayout() {
        self.view.addSubview(tableView)
        self.view.addSubview(emptyView)
        self.view.addSubview(loadMoreButton)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.snp.makeConstraints { (make) -> Void in
            make.left.right.leading.trailing.top.equalToSuperview()
            if(self.hasLoader == true) {
                make.bottom.equalTo(self.loadMoreButton.snp.top).offset(-15)
            }
            print("PRINT TABLE HEIGHT", self.tableView.contentSize.height) // It's 0.0
            make.height.equalTo(1000) // Just trying things
        }
        tableView.isScrollEnabled = false
        
        emptyView.translatesAutoresizingMaskIntoConstraints = false
        emptyView.isHidden = true
        emptyView.textAlignment = .center
        emptyView.snp.makeConstraints { (make) -> Void in
            make.left.right.leading.trailing.equalToSuperview()
            make.top.equalToSuperview().offset(8)
        }
        
        self.loadMoreButton.isHidden = true
        if(self.hasLoader == true) {
            self.loadMoreButton.isHidden = false
            loadMoreButton.translatesAutoresizingMaskIntoConstraints = false
            loadMoreButton.snp.makeConstraints { (make) -> Void in
                make.centerX.equalToSuperview()
                make.top.equalTo(tableView.snp.bottom)
            }
        }
    }
    
    func initActions() {
        loadMoreButton.addTarget(self, action: #selector(self.loadMoreOnClick(sender:)), for: .touchUpInside)
    }


    func loadList(appendItems: Bool) {
        DispatchQueue.main.async {
            self.apiClient.getList(completion: { _ in
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                    // Here I normally do tableView.snp.remakeConstraints { (make) in make.height.equalTo(self.tableView.contentSize.height) } which fires viewDidLoad many times (as much as I have cells)
                }
            })
        }
    }

    func loadMore() {
        self.page += 1
        self.loadList(appendItems: true)
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! Cell
        let currentResource = resourceList[indexPath.row]
        cell.setResource(resource: currentResource)
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.tableView.deselectRow(at: indexPath, animated: true)
        let resource = resourceList[indexPath.row]
        if (resource.getRouteParam() != "") {
            router.setRoute(routeName: resource.getRouteName(), routeParam: 
            resource.getRouteParam())
        }
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }

为了便于阅读,我省略了部分代码。

1 个答案:

答案 0 :(得分:2)

尝试以下操作:

  1. 像这样在 UIViewController 子类中声明一个变量。
private var contentSizeObservation: NSKeyValueObservation?
  1. viewDidLoad() 内或设置 myTableView 时,开始观察 contentSize 的变化。
contentSizeObservation = myTableView.observe(\.contentSize, options: .new, changeHandler: { [weak self] (tv, _) in
    guard let self = self else { return }
    self.myTableViewHeightConstraint.constant = tv.contentSize.height
})
  1. 不要忘记在 deinit 调用中清理它 -
deinit {
    contentSizeObservation?.invalidate()
}

这种方法将确保您的 myTableView 的高度始终与其内容一样大。

相关问题