Search code examples
iosswiftuiviewnslayoutconstraintuistackview

addSubview and addArrangedSubview not showing content


I'm adding a UILabel to a UIView and then adding the UIView to a UIStackView, but the UILabel is not showing.

override func viewDidLoad() {
    super.viewDidLoad()
    
    configureStackView()
    
    label.text = "test"
    containerView.addSubview(label)
    stackView.addArrangedSubview(containerView)
    view.addSubview(stackView)
    
    setStackViewConstraints()
}

func configureStackView() {
    stackView.axis = .vertical
    stackView.distribution = .fill
    stackView.alignment = .fill
    stackView.spacing = 5
}

func setStackViewConstraints() {
     stackView.translatesAutoresizingMaskIntoConstraints = false
     stackView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
     stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
     stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
     stackView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
     stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
 }

I tried setting some sort of size for the view, but doesn't work:

containerView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))

or setting constraints to the label to the containerView for widthAnchor, leadingAnchor, or trailingAnchor, but that doesn't work either.


Solution

  • UIView on its own does not have an intrinsicContentSize, which UIStackView uses to determine the size of the view when placed in the stackView. Either set constraints for the four edges of the label to the edges of the container

    label.topAnchor.constraint(container.topAnchor, constant: myTopConstant).isActive = true
    label.leading....
    label.bottom....
    label.trailing....
    
    label.setContentHuggingPriority(to: .defaultLow, axis: .vertical)
    

    (above, relax the contentHuggingPriority if you are not placing any other views in the stackView; since it has a fixed height and distribution = .fill, your stackView will try to stretch the arrangedViews to fit the height. If the label/container are the only candidates, you'll be breaking constraints with a .required contentHugging on the label)

    or give the container a well-defined height (since the axis of your stackView is vertical)

    containerView.heightAnchor.constraint(equalTo: ....).isActive = true
    

    Also, in your container, set

    translatesAutoresizing... = false