systemLayoutSizeFitting всегда возвращает ноль

#ios #autolayout

#iOS #автозапуск

Вопрос:

На основе документа Apple, systemLayoutSizeFitting предполагается, что при возврате оптимального размера должны соблюдаться текущие ограничения на UIView элемент. Однако всякий раз, когда я запускаю следующий код, я получаю {0, 0} for UIView.layoutFittingCompressedSize и {1000, 1000} для UIView.layoutFittingExpandedSizeSize ввода.

 let mainView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 375, height: 50)))
mainView.backgroundColor = .red
PlaygroundPage.current.liveView = mainView

let subview = UIView()
subview.backgroundColor = .yellow
mainView.addSubview(subview)
subview.snp.makeConstraints { make in
    make.width.equalToSuperview().dividedBy(3.0)
    make.left.top.bottom.equalToSuperview()
}
mainView.setNeedsLayout()
mainView.layoutIfNeeded()

subview.frame

subview.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
  

Я заметил, что если я изменю width ограничение на что-то постоянное, то я получу действительное значение из systemLayoutSizeFitting . Пытаюсь понять, почему происходит такое поведение и возможно ли получить правильное значение из systemLayoutSizeFittingSize(_ size: CGSize) .

Ответ №1:

Документации по этому вопросу, похоже, не хватает.

Похоже, что .systemLayoutSizeFitting это сильно зависит от .intrinsicContentSize элемента. В случае UIView у него нет внутреннего размера содержимого (если вы не переопределили его).

Итак, если связанное ограничение является процентом от другого ограничения, .systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) вернется {0, 0} . Я полагаю, это связано с тем, что связанное ограничение может измениться (на ноль), поэтому минимальное значение фактически равно нулю.

Если вы измените свое .width ограничение на константу (например, mainView.frame.width * 0.3333 ), вы получите допустимое значение размера, поскольку ограничение постоянной ширины становится внутренней шириной.

Например, если ваш subview является UILabel , этот элемент будет иметь собственный размер и .systemLayoutSizeFitting должен возвращать значение размера, которое вы ожидаете.

Вот пример использования UILabel , который продемонстрирует:

 import UIKit
import PlaygroundSupport

let mainView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 375, height: 50)))
mainView.backgroundColor = .red
PlaygroundPage.current.liveView = mainView

let v = UILabel()
v.text = "Testing"
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .green
mainView.addSubview(v)

NSLayoutConstraint.activate([
    v.widthAnchor.constraint(equalTo: mainView.widthAnchor, multiplier: 3.0 / 10.0),
    v.leftAnchor.constraint(equalTo: mainView.leftAnchor),
    v.topAnchor.constraint(equalTo: mainView.topAnchor),
    v.bottomAnchor.constraint(equalTo: mainView.bottomAnchor),
    ])

mainView.setNeedsLayout()
mainView.layoutIfNeeded()

v.frame

v.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
  

Комментарии:

1. Это полностью имеет смысл и согласуется с тем, что у меня также есть. Спасибо за подробное объяснение.