Fuck you UITemporaryLayoutWidth constraint
Today I spent 30 minutes to fix this Auto Layout contstraint warning:
(
"<NSLayoutConstraint:0x600001890f00 UIStackView:0x7ff1d716f520.leading == UILayoutGuide:0x6000002d4a80'UIViewLayoutMarginsGuide'.leading (active)>",
"<NSLayoutConstraint:0x600001890f50 UIStackView:0x7ff1d716f520.trailing == UILayoutGuide:0x6000002d4a80'UIViewLayoutMarginsGuide'.trailing (active)>",
"<NSLayoutConstraint:0x600001890b90 UIView:0x7ff1d716e330.leading == UILayoutGuide:0x6000002d4620'UIViewLayoutMarginsGuide'.leading (active)>",
"<NSLayoutConstraint:0x600001890be0 UIView:0x7ff1d716e330.trailing == UILayoutGuide:0x6000002d4620'UIViewLayoutMarginsGuide'.trailing (active)>",
"<NSLayoutConstraint:0x600001891ae0 '_UITemporaryLayoutWidth' Mocha.CategoryHeaderBar:0x7ff1d71687d0.width == 0 (active)>",
"<NSLayoutConstraint:0x600001890e10 'UIView-leftMargin-guide-constraint' H:|-(15)-[UILayoutGuide:0x6000002d4a80'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':UIView:0x7ff1d716e330 )>",
"<NSLayoutConstraint:0x600001890aa0 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x6000002d4620'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':Mocha.CategoryHeaderBar:0x7ff1d71687d0 )>",
"<NSLayoutConstraint:0x600001890eb0 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6000002d4a80'UIViewLayoutMarginsGuide']-(15)-|(LTR) (active, names: '|':UIView:0x7ff1d716e330 )>",
"<NSLayoutConstraint:0x600001890b40 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6000002d4620'UIViewLayoutMarginsGuide']-(0)-|(LTR) (active, names: '|':Mocha.CategoryHeaderBar:0x7ff1d71687d0 )>"
)
I double check my code, all looks good. The problem is _UITemporaryLayoutWidth
is automatically added by UIKit. Searching StackOverflow doesn’t give me anything immediately helpful.
So I checked Twitter and found _UITemporaryLayoutWidth
is fucked as early as 2017:
One thing I learned is to search _UITemporaryLayoutWidth
with Github Search. I had the luck this time to found two identical issues, from which I learned the reason why UITemporaryLayoutWidth
is added.
In short, UITemporaryLayoutWidth
is added when layoutIfNeeded
is called before layoutSubviews
. I call layoutIfNeeded
in one of my UIControl class.
I call it because this control will do an animation by layouting subViews.
func toggleSelected(selected: Bool, _ animated: Bool) {
self.isSelected = selected
...
self.layoutIfNeeded()
}
To fix this, only do the layout when the view has been added to a UIWindow
.
func toggleSelected(selected: Bool, _ animated: Bool) {
self.isSelected = selected
...
if self.window != nil {
self.layoutIfNeeded()
}
}