Какие дополнительные ограничения ширины и высоты появляются при программном создании UILabel? И как я могу предотвратить их создание?

Я создаю элемент пользовательского интерфейса в своем приложении программно, например:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let label = UILabel()
    label.text = "Just text"
    label.backgroundColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1)
    view.addSubview(label)

    label.translatesAutoresizingMaskIntoConstraints = false
    label.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
    label.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
    view.rightAnchor.constraint(greaterThanOrEqualTo: label.rightAnchor, constant: 20).isActive = true

    view.layoutIfNeeded()
}

UILabel создает и выглядит нормально, но кроме 3-х ограничений из моей метки кода есть также ограничения ширины и высоты

Скриншот иерархии представления отладки: Дополнительные ограничения

Приложение в скриншоте симулятора iOS: Скриншот iOS Simulato

Информация об ограничениях размера метки на консоли отладки:

po ((UIView *)0x7f8573c0ccc0).constraints
<__NSArrayI 0x600000236820>(
<NSContentSizeLayoutConstraint:0x6000000a8b20 UILabel:0x7f8573c0ccc0'Just text'.width == 66 Hug:250 CompressionResistance:750   (active)>,
<NSContentSizeLayoutConstraint:0x6000000a8b80 UILabel:0x7f8573c0ccc0'Just text'.height == 20.3333 Hug:250 CompressionResistance:750   (active)>
)

Здесь есть ограничения по ширине и высоте, которые были созданы автоматически, без моего кода. Я хочу предотвратить их создание.

Ограничения между лейблом и суперпредставлением:

po ((UIView *)((UIView *)0x7f8573c0ccc0).superview).constraints
<__NSArrayI 0x60000028c3f0>(
<NSLayoutConstraint:0x600000284a60 H:|-(20)-[UILabel:0x7f8573c0ccc0'Just text'](LTR)   (active, names: '|':UIView:0x7f8573c0b7b0 )>,
<NSLayoutConstraint:0x6000002854b0 V:|-(20)-[UILabel:0x7f8573c0ccc0'Just text']   (active, names: '|':UIView:0x7f8573c0b7b0 )>,
<NSLayoutConstraint:0x600000285550 H:[UILabel:0x7f8573c0ccc0'Just text']-(>=20)-|(LTR)   (active, names: '|':UIView:0x7f8573c0b7b0 )>,
<NSLayoutConstraint:0x600000285cd0 'UIView-Encapsulated-Layout-Height' UIView:0x7f8573c0b7b0.height == 736   (active)>,
<NSAutoresizingMaskLayoutConstraint:0x600000285d70 h=-&- v=-&- 'UIView-Encapsulated-Layout-Left' UIView:0x7f8573c0b7b0.minX == 0   (active, names: '|':UIWindow:0x7f8573d132d0 )>,
<NSAutoresizingMaskLayoutConstraint:0x600000285eb0 h=-&- v=-&- 'UIView-Encapsulated-Layout-Top' UIView:0x7f8573c0b7b0.minY == 0   (active, names: '|':UIWindow:0x7f8573d132d0 )>,
<NSLayoutConstraint:0x600000285c80 'UIView-Encapsulated-Layout-Width' UIView:0x7f8573c0b7b0.width == 414   (active)>
)

Здесь мы можем посмотреть 3 ограничения с UILabel, созданными моим кодом, и системные ограничения с представлением контейнера и UIWindows

Почему появились ограничения по ширине и высоте?
И могу ли я предотвратить их создание?

2 ответа

Решение

Эти ограничения созданы, потому что UILabel имеет внутренний размер содержимого. Вы можете влиять на эти ограничения, используя приоритеты содержания (CHP) и сопротивления сжатию содержимого (CCRP) на UILabel.

Они будут создаваться всегда, но если вы добавите ограничения с приоритетами выше, чем CHP / CCRP, вы можете переопределить их в макете.

Вы можете добавить ограничение по высоте и ширине программно. Но вы должны игнорировать (не добавлять) ограничение по высоте и ширине, если вы хотите, чтобы ограничение автоматической разметки автоматически обрабатывало высоту и ширину вашего ярлыка в соответствии с размером содержимого.

Ограничение высоты:

label.addConstraint(NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20.0))

Ограничение ширины:

label.addConstraint(NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 20.0))

Ограничение ширины означает меньшее значение с правым якорем, который вы добавили в свой код. Либо вы должны добавить ограничение ширины или правую привязку.

 view.rightAnchor.constraint(greaterThanOrEqualTo: label.rightAnchor, constant: 20).isActive = true

Ограничение ширины будет исправлено, ширина вашей метки, следовательно, правая привязка станет неэффективной.

Я предлагаю игнорировать ограничения по высоте и ширине (не добавлять). Код, который вы показали здесь (а также дизайн интерфейса), подходит для динамического размера UIElement. (Вы можете добавить нижнее ограничение, если хотите добавить любой другой элемент UIElement, расположенный относительно вашей текущей метки.)

Обновление: (для вашего запроса - "Я хочу знать, почему появляются ограничения, пропущенные в моем коде, и как я могу предотвратить это".)

Я попробовал ваш код, и он работает нормально. (что плохого в том, что вы можете видеть в своем коде?)

 let label = UILabel()
    label.text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.  Lorem Ipsum has been the industry's standard dummy text ever since the 1500s. When an unknown printer took a galley of type and scrambled it n book."
    label.numberOfLines = 0
    label.lineBreakMode = .byTruncatingTail
    label.backgroundColor = UIColor.orange
    view.addSubview(label)

    label.translatesAutoresizingMaskIntoConstraints = false
    label.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 120).isActive = true
    label.topAnchor.constraint(equalTo: view.topAnchor, constant: 120).isActive = true
    view.rightAnchor.constraint(greaterThanOrEqualTo: label.rightAnchor, constant: 20).isActive = true

    view.layoutIfNeeded()

Вот результат:

Другие вопросы по тегам