Изменить ограничение высоты для представления, заключенного в UITableViewCell

У меня есть UITableView с настраиваемой ячейкой, содержащей представление.

После отображения представления я хочу изменить высоту вложенного представления.

Я использую функцию updateConstraints фреймворка SnapKit.

Однако я получаю сообщение об ошибке, что обновленное ограничение конфликтует с UIView-Encapsulated-Layout-Height, которое, по-видимому, исходит из начальной установленной высоты.

    "<SnapKit.LayoutConstraint:[email protected]#89 SnapKitTest.NestedView:0x102005ef0.height == 100.0>",
"<SnapKit.LayoutConstraint:[email protected]#70 SnapKitTest.NestedView:0x102005ef0.top == SnapKitTest.TestCell:0x10280e200.top>",
"<SnapKit.LayoutConstraint:[email protected]#70 SnapKitTest.NestedView:0x102005ef0.bottom == SnapKitTest.TestCell:0x10280e200.bottom>",
"<NSLayoutConstraint:0x280058a50 'UIView-Encapsulated-Layout-Height' SnapKitTest.TestCell:0x10280e200.height == 20   (active)>"
)

Will attempt to recover by breaking constraint 
<SnapKit.LayoutConstraint:[email protected]#89 SnapKitTest.NestedView:0x102005ef0.height == 100.0>

Ниже приведен исходный код для запуска примера приложения:

import UIKit
import SnapKit

class ViewController: UIViewController {

    let tableView = UITableView.init(frame: .zero)

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(tableView)
        tableView.snp.makeConstraints { make in
            make.edges.equalTo(self.view)
        }

        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "X")
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 100
        tableView.delegate = self
        tableView.dataSource = self
    }


    override func viewDidAppear(_ animated: Bool) {
        if let c = tableView.cellForRow(at: IndexPath(row: 5, section: 0)) as? TestCell {
            c.nestedView.snp.updateConstraints { make in
                make.height.equalTo(100)
            }
        } else {
            print("didnt geht cell")
        }
    }

}


extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        if indexPath.row == 5 {
            let c = TestCell.init(style: .default, reuseIdentifier: nil)

            return c


        }

        let c = tableView.dequeueReusableCell(withIdentifier: "X")
        c?.backgroundColor = .orange
        return c!
    }

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


}


class TestCell: UITableViewCell {
    let nestedView = NestedView()

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


        addSubview(nestedView)
        nestedView.snp.makeConstraints { make in
            make.edges.equalTo(self)
        }
        backgroundColor = .blue

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


class NestedView: UIView {

    init() {
        super.init(frame: .zero)
        backgroundColor = .yellow

        snp.makeConstraints { make in
            make.height.equalTo(20)
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

person Pascal    schedule 05.10.2018    source источник
comment
не делай этого так. установите ограничения внутри метода cellForRowAt и перезагрузите таблицу. и убедитесь, что у вас есть UITableView.automaticDimension   -  person RJE    schedule 05.10.2018
comment
спасибо, что решил проблему :)   -  person Pascal    schedule 05.10.2018


Ответы (2)


Ты не хочешь этого делать. Насколько я знаю, это не сработает. Вам необходимо установить ограничения либо в init вашей ячейки. Или в вашей cellForRow функции.

Итак, в приведенных ниже кодах я изменил ваш и добавил свойство (ограничение по высоте) вашего NestedView внутри вашей TestCell ячейки. И я обновляю эту высоту внутри cellForRow.

Изменить: если вы хотите переключить высоту ячейки, конечно, вы делаете это так же, вам просто нужно перезагрузить строки / разделы или целые данные вашего tableView.

ViewController.swift

import UIKit
import SnapKit

class ViewController: UIViewController {

    let tableView = UITableView.init(frame: .zero)

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(tableView)
        tableView.snp.makeConstraints { make in
            make.edges.equalTo(self.view)
        }

        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "X")
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 100
        tableView.delegate = self
        tableView.dataSource = self
    }

}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        if indexPath.row == 5 {
            let c = TestCell.init(style: .default, reuseIdentifier: nil)
            c.constraint_HeightOfNestedView?.update(offset: 100.0)
            return c


        }

        let c = tableView.dequeueReusableCell(withIdentifier: "X")
        c?.backgroundColor = .orange
        return c!
    }

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

TestCell.swift

import SnapKit

class TestCell: UITableViewCell {
    var constraint_HeightOfNestedView: Constraint?
    let nestedView = NestedView()

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


        addSubview(nestedView)
        nestedView.snp.makeConstraints { make in
            make.edges.equalTo(self)
            self.constraint_HeightOfNestedView = make.height.equalTo(20.0).priority(999).constraint
        }
        backgroundColor = .blue

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

NestedView.swift

import UIKit

class NestedView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = .yellow
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
person Glenn Posadas    schedule 05.10.2018

Чтобы изменить высоту subview В UITableViewCell вы должны установить высоту желаемого вида, а также установить приоритет 999. Конечно, вам нужно использовать ячейки с самодиагностикой :)

Бывший. Мое требование было,

UITableViewCell 
  -- contentView
     -- UIImageView (pinned to all sides in contentView)

Внутри cellForRow,

let constraint = cell.myImageView.constraint(equalTo: cell.myImageView.widthAnchor, multiplier: 2.0)//change multiplier as you need or directly set the height to any value
        constraint.priority = UILayoutPriority(rawValue: 999)
        constraint.isActive = true
person infiniteLoop    schedule 28.05.2021