I have a UITableView and I want to display a dynamic header at the top of the table. I am trying to do this using tableHeaderView. The header contains a titleLabel and a descriptionLabel arranged inside a UIStackView. I also want to add padding around the UIStackView.
Here is the simplified version of my CustomHeaderView:
class CustomHeaderView: UIView {
var padding: UIEdgeInsets = .zero
// MARK: - UI Elements
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private lazy var descriptionLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private lazy var stackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [titleLabel, descriptionLabel])
stackView.axis = .vertical
stackView.alignment = .fill
stackView.spacing = 8
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
override init(frame: CGRect = .zero) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
private func setupView() {
addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: topAnchor, constant: padding.top),
stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding.left),
stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding.right),
stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -padding.bottom),
])
}
}
In my ViewController, I set up the header like this:
override func viewDidLoad() {
super.viewDidLoad()
let headerView = CustomHeaderView()
headerView.padding = .init(top: 70, left: 23, bottom: 8, right: 23)
tableView.tableHeaderView = headerView
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.updateHeaderViewHeight()
}
I use the following extension to dynamically update the height of the header:
extension UITableView {
func updateHeaderViewHeight() {
guard let headerView = self.tableHeaderView else { return }
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
let size = headerView.systemLayoutSizeFitting(CGSize(width: self.bounds.width, height: 0))
if headerView.frame.size.height != size.height {
headerView.frame.size.height = size.height
self.tableHeaderView = headerView
}
}
}
The setup works as expected, and the header adjusts its size dynamically based on the content. However, I am encountering Auto Layout warnings.
First warning:
(
"<NSLayoutConstraint:0x600002137250 V:|-(70)-[UIStackView:0x10312c3f0] (active, names: '|':VeriQSDK.CustomHeaderView:0x101504910 )>",
"<NSLayoutConstraint:0x600002134cd0 UIStackView:0x10312c3f0.bottom == VeriQSDK.CustomHeaderView:0x101504910.bottom - 8 (active)>",
"<NSLayoutConstraint:0x600002143f70 'UISV-canvas-connection' UIStackView:0x10312c3f0.top == UILabel:0x10312cba0.top (active)>",
"<NSLayoutConstraint:0x600002143de0 'UISV-canvas-connection' V:[UILabel:0x10312d130]-(0)-| (active, names: '|':UIStackView:0x10312c3f0 )>",
"<NSLayoutConstraint:0x600002143f20 'UISV-spacing' V:[UILabel:0x10312cba0]-(8)-[UILabel:0x10312d130] (active)>",
"<NSLayoutConstraint:0x600002148000 'UIView-Encapsulated-Layout-Height' VeriQSDK.CustomHeaderView:0x101504910.height == 0 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600002143f20 'UISV-spacing' V:[UILabel:0x10312cba0]-(8)-[UILabel:0x10312d130] (active)>
Second warning:
(
"<NSLayoutConstraint:0x600002137250 V:|-(70)-[UIStackView:0x10312c3f0] (active, names: '|':VeriQSDK.CustomHeaderView:0x101504910 )>",
"<NSLayoutConstraint:0x600002134cd0 UIStackView:0x10312c3f0.bottom == VeriQSDK.CustomHeaderView:0x101504910.bottom - 8 (active)>",
"<NSLayoutConstraint:0x600002148000 'UIView-Encapsulated-Layout-Height' VeriQSDK.CustomHeaderView:0x101504910.height == 0 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600002134cd0 UIStackView:0x10312c3f0.bottom == VeriQSDK.CustomHeaderView:0x101504910.bottom - 8 (active)>
The warnings seem to be related to the UIView-Encapsulated-Layout-Height constraint, which forces the CustomHeaderView height to 0.
How can I properly manage padding and dynamically adjust the tableHeaderView height without encountering these Auto Layout warnings?