Если они ограничены, чтобы быть равными, как размеры кадра могут быть разными?
Поскольку ограничения являются просто инструкциями.Пока эти инструкции не выполнены, они просто инструкции и не более.Это как список покупок;Вы можете видеть, что молоко есть в списке, но вы тогда не говорите: «Так почему же в холодильнике нет молока?». Вы также должны купить молоко.
Что ж, среда выполнения не покупает молоко до тех пор, пока вы не напечатаете описания.Макет не происходит сразу;это происходит во время компоновки, то есть после того, как весь ваш код перестал выполняться и текущая транзакция CAT зафиксирована.После этого два вида будут иметь одинаковые размеры.
Обратите внимание, что я не просто говорю о том, что первый тайм-аут происходит.Макет происходит периодически в течение всей жизни представления, поскольку происходят события, запускающие макет.Но между этими моментами вполне возможно, что другой код придет и установит кадр представления вручную на что-то другое.Он не будет изменен обратно на то, что диктуют ограничения, пока макет не будет запущен снова.
(И, конечно, он включает в себя layoutSubviews
и viewDidLayoutSubviews
сами. В этот момент происходит автоматическое расположение, но ваш код может прийтиа также переопределите то, что сделал autolayout.)
Просто чтобы понять суть, вот полный код приложения, которое вводит нас в ситуацию, аналогичную описанной вами:
func delay(_ delay:Double, closure:@escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let v = UIView()
v.backgroundColor = .red
v.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(v)
NSLayoutConstraint.activate([
v.topAnchor.constraint(equalTo:self.view.topAnchor),
v.leadingAnchor.constraint(equalTo:self.view.leadingAnchor),
v.trailingAnchor.constraint(equalTo:self.view.trailingAnchor),
v.bottomAnchor.constraint(equalTo:self.view.bottomAnchor),
])
delay(5) {
v.frame = v.frame.insetBy(dx: 30, dy: 30)
print(v.frame)
print(self.view.frame)
print(self.view.constraints)
}
}
}
Обратите внимание на распечатку (для ясности я отредактировал некоторые ограничения):
(30.0, 30.0, 354.0, 676.0)
(0.0, 0.0, 414.0, 736.0)
[
<NSLayoutConstraint:0x600000083570 V:|-(0)-[UIView:0x7fede9d07190] (active, names: '|':UIView:0x7fede9f0d230 )>,
<NSLayoutConstraint:0x6000000957c0 H:|-(0)-[UIView:0x7fede9d07190] (active, names: '|':UIView:0x7fede9f0d230 )>,
<NSLayoutConstraint:0x600000094c30 UIView:0x7fede9d07190.trailing == UIView:0x7fede9f0d230.trailing (active)>,
<NSLayoutConstraint:0x600000095f40 UIView:0x7fede9d07190.bottom == UIView:0x7fede9f0d230.bottom (active)>,
...
]
Это так же, как ваша распечатка: ограничения говорят, что края двух видов должны быть равны, но их рамки имеют разные размеры.Так что то, о чем вы пишете, действительно возможно.