ios - 将 View 添加到 UIStackView 后,UITableViewCell 不会更新高度

标签 ios swift uitableview tableviewcell uistackview

我在 UITableViewCellcontentView 中有一个 UIStackView。根据用户交互,我在 UIStackView 中添加/删除项目。修改 UIStackView 中的项目后,我希望 cell 相应地更新它的高度。但是,它不会更新它的高度,除非我调用 tableView.reloadData()。但是,在 cellForRowAtIndexPath/willDisplayCell 中调用 reloadData() 变为递归。

在运行时根据 UIStackView 中的项目调整 cell 高度的正确方法是什么?

我使用 UITableViewAutomaticDimension

更新问题:

Here是我正在尝试做的事情的简单原型(prototype)。

我的实际问题是使单元格出队。

在原型(prototype)中,我有 2 个可重复使用的单元格和 3 行。对于第 0 行和第 2 行,我将 cellA 出列,对于第 1 行,我将 cellB 出列。以下是我使用的条件的概述。

if indexPath.row == 0 {
    // dequeue cellA with 2 items in stackView
}

if indexPath.row == 1 {
    // dequeue cellB with 25 items in stackView
}

if indexPath.row == 2 {
    // dequeue cellA with 8 items in stackView
}

但是输出是, 第 0 行在 stackView 中包含 2 个项目 - 预期 第 1 行在 stackView 中包含 25 个项目 - 预期 第 2 行包含 stackView 中的 2 个项目 - 意外,第 0 行已出队

我还尝试删除 cellForRowAtIndexPathstackView 的所有排列 subview 。但是,这样做会在滚动时闪烁 UI。我怎样才能设法获得所需的输出?

最佳答案

我认为问题是何时您将 View 添加到堆栈 View 。

一般来说,添加元素应该在单元格初始化时进行。

willDisplay cell: 是处理单元格内容的修改属性的地方。

如果您将代码从 willDisplay cell: 移动到 cellForRowAt indexPath:,您应该会看到很大的不同。

我刚刚对您链接到的代码进行了一项更改,现在行会根据堆栈 View 内容自动调整大小。

编辑:查看更新后的代码...问题仍然是您在错误的位置添加了 arrangedSubviews。你通过调用 reloadData() 来复合它。

第二次编辑:当重复使用单元格时忘记处理之前添加的 subview 。

更新代码...将您的 ViewController 代码替换为:

//
//  ViewController.swift
//

import UIKit

class ViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.tableFooterView = UIView()
        tableView.estimatedRowHeight = 56
    }

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

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        var cell = UITableViewCell()

        if indexPath.row == 0 || indexPath.row == 2 {
            cell = tableView.dequeueReusableCell(withIdentifier: "cell")!

            if let stackView = cell.viewWithTag(999) as? UIStackView {
                let numberOfItemsInStackView = (indexPath.row == 0) ? 2 : 8
                let color = (indexPath.row == 0) ? UIColor.gray : UIColor.black

                // cells are reused, so clear out any previously added subviews...
                // but leave the first view that is part of the cell prototype
                while stackView.arrangedSubviews.count > 1 {
                    stackView.arrangedSubviews[1].removeFromSuperview()
                }

                // use "i" so we can count
                for i in 1...numberOfItemsInStackView {

                    // use label instead of view so we can number them for testing
                    let newView = UILabel()
                    newView.text = "\(i)"
                    newView.textColor = .yellow

                    // add a border, so we can see the frames
                    newView.layer.borderWidth = 1.0
                    newView.layer.borderColor = UIColor.red.cgColor

                    newView.backgroundColor = color
                    let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 54)
                    heightConstraint.priority = 999
                    heightConstraint.isActive = true
                    stackView.addArrangedSubview(newView)
                }
            }

        }

        if indexPath.row == 1 {
            cell = tableView.dequeueReusableCell(withIdentifier: "lastCell")!

            if let stackView = cell.viewWithTag(999) as? UIStackView {
                let numberOfItemsInStackView = 25

                // cells are reused, so clear out any previously added subviews...
                // but leave the first view that is part of the cell prototype
                while stackView.arrangedSubviews.count > 1 {
                    stackView.arrangedSubviews[1].removeFromSuperview()
                }

                // use "i" so we can count
                for i in 1...numberOfItemsInStackView {

                    // use label instead of view so we can number them for testing
                    let newView = UILabel()
                    newView.text = "\(i)"
                    newView.textColor = .yellow

                    // add a border, so we can see the frames
                    newView.layer.borderWidth = 1.0
                    newView.layer.borderColor = UIColor.red.cgColor

                    newView.backgroundColor = UIColor.darkGray
                    let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 32)
                    heightConstraint.priority = 999
                    heightConstraint.isActive = true
                    stackView.addArrangedSubview(newView)
                }
            }

        }

        return cell

    }

//    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
//        if cell.reuseIdentifier == "cell" {
//            if let stackView = cell.viewWithTag(999) as? UIStackView {
//                let numberOfItemsInStackView = (indexPath.row == 0) ? 2 : 8
//                let color = (indexPath.row == 0) ? UIColor.gray : UIColor.black
//                guard stackView.arrangedSubviews.count == 1 else { return }
//                for _ in 1...numberOfItemsInStackView {
//                    let newView = UIView()
//                    newView.backgroundColor = color
//                    let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 54)
//                    heightConstraint.priority = 999
//                    heightConstraint.isActive = true
//                    stackView.addArrangedSubview(newView)
//                }
//                tableView.reloadData()
//            }
//        }
//        
//        if cell.reuseIdentifier == "lastCell" {
//            if let stackView = cell.viewWithTag(999) as? UIStackView {
//                let numberOfItemsInStackView = 25
//                guard stackView.arrangedSubviews.count == 1 else { return }
//                for _ in 1...numberOfItemsInStackView {
//                    let newView = UIView()
//                    newView.backgroundColor = UIColor.darkGray
//                    let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 32)
//                    heightConstraint.priority = 999
//                    heightConstraint.isActive = true
//                    stackView.addArrangedSubview(newView)
//                }
//                tableView.reloadData()
//            }
//        }
//    }

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

关于ios - 将 View 添加到 UIStackView 后,UITableViewCell 不会更新高度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44799575/

相关文章:

ios - Swift:App Delegate 应该如何获取对 View Controller 的引用?

iphone - EXEC_BAD_ACCESS 调用 CGImage

ios - 如何使用 swift 在 xcode 中删除(或不使用)启动屏幕 Storyboard

ios - CIFace 特征边界

swift - 如何保证Grand Central Dispatch中的一项功能接连运行?

ios - 在 Swift 中测试 FIRDataSnapshot

ios - 如何将数据传递给嵌套 Controller (UIContainerView)?

ios - popoverPresentationController 从 iPhone 上的 UITableViewController 模态显示

objective-c - Xcode 4.2 与 Storyboard : Program received signal: “EXC_BAD_ACCESS”

ios - Xcode UITableView 放置和单元格分隔符