Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift 4.2 TableViewCell动态高度编程_Ios_Swift_Uitableview_Nslayoutconstraint - Fatal编程技术网

Ios Swift 4.2 TableViewCell动态高度编程

Ios Swift 4.2 TableViewCell动态高度编程,ios,swift,uitableview,nslayoutconstraint,Ios,Swift,Uitableview,Nslayoutconstraint,这不是重复的问题,因为这个问题没有真正的解决方案 我正在尝试使用约束通过其内容实现UITableViewcell动态高度,但得到布局警告: 将尝试通过打破约束进行恢复 在UIViewAlertForUnsatifiableConstraints处创建符号断点 要在调试器中捕获此信息。研究方法 中列出的UIView上的UIConstraintBasedLayoutDebugging类别 也可能有帮助。2019-03-15 12:27:52.085475+0400 TableCell动态灯光[31

这不是重复的问题,因为这个问题没有真正的解决方案

我正在尝试使用约束通过其内容实现
UITableViewcell
动态高度,但得到布局警告:

将尝试通过打破约束进行恢复

在UIViewAlertForUnsatifiableConstraints处创建符号断点 要在调试器中捕获此信息。研究方法 中列出的UIView上的UIConstraintBasedLayoutDebugging类别 也可能有帮助。2019-03-15 12:27:52.085475+0400 TableCell动态灯光[31984:1295380] [LayoutConstraints]无法同时满足约束。 可能以下列表中至少有一个约束是 你不会想要的。尝试以下方法:(1)查看每个约束并尝试 找出你不期望的;(2) 查找添加了 一个或多个不需要的约束,然后修复它。( "", "", "", “”)

我检查了一些线程:

什么是正确的解决方案,我遗漏了什么

视图控制器:

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    lazy var tableView: UITableView = {
        let table = UITableView()
        table.backgroundColor = .white
        table.translatesAutoresizingMaskIntoConstraints = false
        table.register(TableViewCell.self, forCellReuseIdentifier: "cellId")
        table.dataSource = self
        table.delegate = self
        return table
    }()


    let arr:[Int:UIColor] = [345: UIColor.random, 422: .random, 23: .random, 344: .random,200: .random,140: .random]

    var pickerDataVisitLocation = [203: "Home", 204: "Hospital", 205: "Other"]

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .red

        self.view.addSubview(tableView)
//
        tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
        tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
        tableView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        tableView.tableFooterView = UIView()
    }
}

extension ViewController {

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

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

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

        let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! TableViewCell
        let value:UIColor = Array(arr)[indexPath.row].value
        let key = Array(arr)[indexPath.row].key

        cell.setupViews(he: CGFloat(key), color: value)
        return cell
    }

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

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
}

extension UIColor {
    static var random: UIColor {
        return UIColor(red: .random(in: 0...1),
                       green: .random(in: 0...1),
                       blue: .random(in: 0...1),
                       alpha: 1.0)
    }
}
TableViewCell:

    import UIKit

    class TableViewCell: UITableViewCell {


        override func awakeFromNib() {
            super.awakeFromNib()


        }

        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)


        }

        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }

        func setupViews(he:CGFloat, color:UIColor) {

            let v:UIView = UIView()
            v.translatesAutoresizingMaskIntoConstraints = false
            self.addSubview(v)

            v.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
            v.backgroundColor = color
            v.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
            v.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
            v.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
            v.heightAnchor.constraint(equalToConstant: he).isActive = true
            #warning("here is constraint error conflict with bottomAnchor and heightAnchor, need correct solution")
        }

    }

在您的情况下,高度在dataSource
arr
中可用,因此您不需要:

  • 高度限制
  • estimatedHeightForRowAtIndexPath
  • 您只需在
    heightforrowatinexpath
    中返回实际高度,但首先您的数据源
    arr:[Int:UIColor]
    是一个
    字典
    ,我不依赖它的顺序,让我们将其更改为
    元组的
    数组

    var dataSource: [(height: CGFloat, color: UIColor)] = [
        (345, .random),
        (422, .random),
        (23, .random),
        (344, .random),
        (200, .random),
        (140, .random)
    ]
    
    现在使用以下UITableView委托/数据源方法:

    extension ViewController: UITableViewDataSource, UITableViewDelegate {
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.dataSource.count
        }
    
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return dataSource[indexPath.row].height
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! TableViewCell
            cell.setupViews(color: dataSource[indexPath.row].color)
            return cell
        }
    
    }
    

    由于您不需要高度约束,我从
    setupview
    方法中删除了
    he
    参数您做错了几件事

    首先,重复使用单元格(因此使用了
    dequeueReusableCell
    ),但是每次重复使用单元格时,您的
    setupViews()
    func都会添加一个新的子视图

    这意味着当你滚动,单元格被重复使用时,你会得到2,3,4。。。十几个子视图,都有冲突的约束

    addSubview()
    移动到单元格中的公共初始化函数,以便只创建和添加一次视图

    这也是您应该设置约束的地方

    要在设计应用程序时更改子视图的高度,您需要更改子视图高度约束的
    .constant

    这是你修改过的代码。我在代码中添加了足够多的注释,应该很清楚:

    class HattoriTableViewCell: UITableViewCell {
    
        // the view to add as a subview
        let myView: UIView = {
            let v = UIView()
            v.translatesAutoresizingMaskIntoConstraints = false
            return v
        }()
    
        // the constraint we'll use for myView's height
        var myViewHeightConstraint: NSLayoutConstraint!
    
        override func awakeFromNib() {
            super.awakeFromNib()
            commonInit()
        }
    
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
            commonInit()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
        }
    
        func commonInit() -> Void {
    
            // add the subview
            self.addSubview(myView)
    
            // constrain it to all 4 sides
            myView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
            myView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
            myView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
            myView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    
            // create the height constraint
            myViewHeightConstraint = myView.heightAnchor.constraint(equalToConstant: 1)
    
            // needs Priority less-than 1000 (default) to avoid breaking constraints
            myViewHeightConstraint.priority = UILayoutPriority.init(999)
    
            // activate it
            myViewHeightConstraint.isActive = true
    
        }
    
        func setupViews(he:CGFloat, color:UIColor) {
    
            // set myView's background color
            myView.backgroundColor = color
    
            // change myView's height constraint constant
            myViewHeightConstraint.constant = he
    
        }
    
    }
    
    class HattoriViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
        lazy var tableView: UITableView = {
            let table = UITableView()
            table.backgroundColor = .white
            table.translatesAutoresizingMaskIntoConstraints = false
            table.register(HattoriTableViewCell.self, forCellReuseIdentifier: "cellId")
            table.dataSource = self
            table.delegate = self
            return table
        }()
    
    
        let arr:[Int:UIColor] = [345: UIColor.random, 422: .random, 23: .random, 344: .random,200: .random,140: .random]
    
        var pickerDataVisitLocation = [203: "Home", 204: "Hospital", 205: "Other"]
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.backgroundColor = .red
    
            self.view.addSubview(tableView)
            //
            tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
            tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
            tableView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
            tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
            tableView.tableFooterView = UIView()
    
            // use a reasonable value -- such as the average of what you expect (if known)
            tableView.estimatedRowHeight = 200
        }
    }
    
    extension HattoriViewController {
    
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return arr.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
            let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! HattoriTableViewCell
    
            let value:UIColor = Array(arr)[indexPath.row].value
            let key = Array(arr)[indexPath.row].key
    
            cell.setupViews(he: CGFloat(key), color: value)
    
            return cell
        }
    
        // NOT NEEDED
    //  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    //      return UITableView.automaticDimension
    //  }
    //
    //  func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    //      return UITableView.automaticDimension
    //  }
    
    }
    
    extension UIColor {
        static var random: UIColor {
            return UIColor(red: .random(in: 0...1),
                           green: .random(in: 0...1),
                           blue: .random(in: 0...1),
                           alpha: 1.0)
        }
    }
    

    我也有同样的问题,但原因不同,我想与大家分享。

    我只需重写
    layoutSubviews()
    方法来添加自定义布局

    但是我没有在初始值设定项中调用
    layoutifneedd()
    方法来激活它们,而只是在单元格出列并重新使用时才激活布局

    以下是我的代码,供您在遇到相同问题时参考:

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    
        contentView.addSubviews(containerView)
        containerView.addSubviews(titleLabel, subtitleLabel, activteSwitch)
    
        layoutIfNeeded() // Required to triger the overriden layoutSubviews() upon initialization
    }
    
    // However, I shouldn't override this method or add any constraints here
    override func layoutSubviews() {
        let margin: CGFloat = 8
    
        containerView.snapToEdges()
        NSLayoutConstraint.activate([
            activteSwitch.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -margin),
            activteSwitch.centerYAnchor.constraint(equalTo: containerView.centerYAnchor),
    
            titleLabel.topAnchor.constraint(equalTo: containerView.topAnchor, constant: margin),
            titleLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: margin),
            titleLabel.trailingAnchor.constraint(equalTo: activteSwitch.leadingAnchor, constant: -margin),
    
            subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: margin),
            subtitleLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: margin),
            subtitleLabel.trailingAnchor.constraint(equalTo: activteSwitch.leadingAnchor, constant: -margin),
            subtitleLabel.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -margin)
    
        ])
    }
    

    如果您已经知道每个项目的确切高度,为什么要使用带约束的动态高度?首先删除
    func tableView(u tableView:UITableView,heightForRowAt indexath:indexPath)->CGFloat{return UITableView.automaticDimension}
    警告如此简单,设置底部锚定或高度锚定都不设置,如果高度大于等于,则无需设置底部锚定constraint@Vinodh不管用,如果我只使用
    bottomAnchor
    heightAnchor
    你可以测试它,谢谢你的建议,但我的目标是通过内容获得
    UITableViewCell
    动态高度,例如从云加载图像或放置
    UICollectionView
    设置
    heightConstraint。优先级
    低于1000解决了我的问题。谢谢如果我们不仅有一个视图,而且有8-10个调整大小的视图,因此需要行高的最终值,该怎么办?当我尝试这样做时,内容将覆盖下一个单元格(未调整大小)@Oleksandr-只要您有完整有效的垂直约束链,自动布局将正确调整单元格大小。如果您得到的内容是“覆盖下一个单元格”,那么您的约束有问题。我的窍门是在
    commonInit
    方法中设置高度约束,而不是在
    updateViewConstraints
    方法中设置所有其他约束。谢谢