In your test project, if I run on an iPhone, I'm not seeing layoutSubviews()
being called in the background. It only happens on iPad.
That's because your app supports Multitasking:
- When your app is deactivated, iOS resizes it into different sizes in order to take snapshots of it for the app switcher. Those resizes cause your view's
layoutSubviews()
to be called. That's completely normal.
- iOS then returns your app to the original size.
The real problem is that you are creating a "layout loop". Your code in layoutSubviews()
is causing your own view's layout to be invalidated, so the system needs to run the layout process again. Then layout runs, you do it again, and it happens all over again.
Specifically, the cause is:
self.font = UIFont(name: fontName, size: fontSize)
Changing your label's font causes its intrinsicSize to change, which means that its superviews may need their layout to be updated, so the layout process needs to run again. It's a bad idea to do this in layoutSubviews()
because it causes layout loops. You should really only change properties of your subviews, not your view itself.
Why do you think you need to do this in layoutSubviews()
? There is probably a better place to put it, outside of the layout process. In your example, I don't see how this code does anything useful at all.
It would make more sense to set adjustsFrameSizeToWidth
once, and then don't do anything in layoutSubviews()
:
override init(frame: CGRect) {
super.init(frame: frame)
self.adjustsFontSizeToFitWidth = true
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.adjustsFontSizeToFitWidth = true
}
If you're trying to change your font's size depending on the size class, you can do it in code by overriding traitCollectionDidChange()
:
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
var fontSize: CGFloat
if (self.traitCollection.horizontalSizeClass == .Regular) {
fontSize = 70
}
else {
fontSize = 30
}
self.font = UIFont(name: fontName, size:fontSize)
}