On iOS 11 many of our layouts are breaking due to labels apparently misreporting their intrinsicContentSize.
The bug seems to manifest worst when a UILabel is wrapped in another view that attempts to implement intrinsicContentSize
itself. Like so (simplified & contrived example):
class LabelView: UIView {
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() {
self.label.textColor = .black
self.label.backgroundColor = .green
self.backgroundColor = .red
self.label.numberOfLines = 0
self.addSubview(self.label)
self.label.translatesAutoresizingMaskIntoConstraints = false
self.label.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
self.label.trailingAnchor.constraint(lessThanOrEqualTo: self.trailingAnchor).isActive = true
self.label.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
self.label.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
override var intrinsicContentSize: CGSize {
let size = self.label.intrinsicContentSize
print(size)
return size
}
}
The intrinsicContentSize
of the UILabel is very distinctive and looks something like: (width: 1073741824.0, height: 20.5)
. This causes the layout cycle to give far too much space to the view's wrapper.
This only occurs when compiling for iOS 11 from XCode 9. When running on iOS 11 compiled on the iOS 10 SDK (on XCode 8).
On XCode 8 (iOS 10) the view is rendered correctly like so:
on XCode 9 (iOS 11) the view is rendered like this:
A Gist with full playground code demonstrating this issue is here.
I have filed a radar for this and have at least one solution to the problem (see answer below). I wonder if anyone else has had this problem or has alternative approached you might try.