Now here’s a weird issue that appeared in iOS 10, I found myself saying one day. I was seeing an iOS button’s title change color as a I navigated from one scene to the next. It got worse. When I navigated back, the button’s title color stayed the wrong color. It was the same color as all the labels in the iOS app. What’s going on?
We dug in deeper and discovered something. There was a nasty appearance proxy color issue where the appearance proxy would change the color of the
UIButton‘s title text color even though the code was explicitly setting the color. In fact, the appearance proxy would set it to be the same color as it has configured for all
UILabel objects. The configuration code for labels was like this:
UILabel.appearance().textColor = labelTextColor()
Since a UIButton contains a UILabel, that might make sense. How does one fix this situation?
The answer to fixing it was discovered after thinking about what was read in this Stack Overflow post titled Appearance Proxy overridden when resetting text:
iOS applies appearance changes when a view enters a window, it doesn’t change the appearance of a view that’s already in a window.
It turns out the code to explicitly set the color on the
UIButton was getting called before the view appeared on the screen aka
viewWillAppear. Once the view appeared on the screen, the appearance proxy would set the button’s label’s text color aka button title color.
As a side note, this only seemed to happen when using
setAttributedTitle on the button as opposed to calling
setTitle separately. Unfortunately, we wanted different parts of the text to be different sizes. So, using
setAttributedTitle still seemed like the thing we should do.
Given all that knowledge, we called
setNeedsLayout on the
viewWillDisappear That fixed everything up! The button no longer appeared to change color when switching between screens. Hurrah!