Search code examples
iosautolayoutuilabeluistackview

UILabel breaks early inside UIStackView


Given the view hierarchy:

UIStackView
--UILabel
--UISwitch

The label breaks too early, even if it can be fit to a single line.

Setting numberOfLines = 1 forces the label to be laid out correctly.

How to make UILabel perform line break only when needed?

Code:

  private lazy var title: UILabel = {
    let v = UILabel()
    v.numberOfLines = 0
    return v
  }()

  private lazy var toggle = UISwitch()
  private lazy var stack = UIStackView(axis: .horizontal,
                                       distribution: .equalSpacing,
                                       alignment: .center,
                                       views: [title,
                                               toggle])
  func setupConstraints() {
    stack.snp.makeConstraints { (make) in
      make.edges.equalTo(contentView.layoutMarginsGuide)
    }
  }

Result: Bug

Setting numberOfLines = 1 gets me what I'd like to achieve, but the label looses its multi-line functionality:

Desired behavior

How to force the desired behavior without losing support for multi-line labels?

When there is a lot of horizontal space, the label gets laid out correctly no matter of the numberOfLines property:

enter image description here


Solution

  • Set your UISwitch's content hugging and resistance priority to 1000.

    And stack view distribution and alignment to fill.

    Extra Note - If you want label and switch to be top aligned, then set alignment to top.