Can't programmatically change color set in storyboard as color from xcassets catalog

旧街凉风 提交于 2019-12-29 00:47:08

问题


When I set color of some property in Storyboard (for example textColor of my UILabel) as color created as New Color Set in xcassets catalog

then I can't programmatically change this color on the first attempt:

label.textColor = UIColor(named: "HighlightedGreen")

... note that I'm calling it from data source method cellForItemAt.

Hack: I can solve it by setting this color in Storyboard for any other color picked from color picker but I want to know why is this happening.

So, why is this happening?


回答1:


When a UIView subClass like UITableViewCell is loaded from the Storyboard/Xib, it applies the attributes specified in Attribute Inspector to all the subViews. We have the following callback methods to know when a view is loaded from the Storyboard/Xib,

override func prepareForInterfaceBuilder() {
    super.prepareForInterfaceBuilder()        
}

override func awakeFromNib() {
    super.awakeFromNib()
}

These methods could be good candidates to add/remove a subView but they are not supposed to update the subView's size or some of attribute inspector related properties. The recommended method to update subViews is when the super view finishes loading and applying all the attribute inspector properties and calls layoutSubviews. So then you should apply any cosmetic change to a subView. e.g,

override func layoutSubviews() {
    super.layoutSubviews()

    label.textColor = UIColor(named: "HighlightedGreen")
}

For a UITableViewCell, any object implementing UITableViewDataSource also guarantees a delegate method to apply any cosmetic change before the cell is being displayed as below, So this is also another good candidate to change the color.

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    (cell as! MyListTableViewCell).label.textColor = UIColor(named: "HighlightedGreen")
}



回答2:


The real answer is that this is closer to a bug. In iOS 13 there is no problem overriding a color asset set in IB with any other color programmatically.

I grabbed some logs from an iOS 12 debug session where I attempted what the OP is doing:

Cell 1

At awakeFromNib: UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6
Setting background color to: UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6
At layoutSubviews: kCGColorSpaceModelRGB 0.235 0.235 0.263 0.6

Cell 2

At awakeFromNib: UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6
Setting background color to: kCGColorSpaceModelRGB 0.490196 0.760784 0.262745 1
At layoutSubviews: kCGColorSpaceModelRGB 0.235 0.235 0.263 0.6

In iOS 13, the logs (and the results) are different:

Cell 1

At awakeFromNib: UIDynamicCatalogColor: 0x600003e83600; name = My Background Color
Setting background color to: UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6
At layoutSubviews: UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6

Cell 2

At awakeFromNib: UIDynamicCatalogColor: 0x600003e99290; name = My Background Color
Setting background color to: UIDynamicCatalogColor: 0x600003e99020; name = Button Green
At layoutSubviews: UIDynamicCatalogColor: 0x600003e99350; name = Button Green

It seems that there is a timing issue with when iOS 12 is translating the named color to the color space that it uses, occurring during layoutSubviews() so attempting to override the color before then is futile. However, iOS 13 seems to use UIDynamicCatalogColor natively without the translation, so there is no timing issue.

Color Assets seem to be a bit of an afterthought for Xcode overall. Good luck renaming them after they've been used throughout your app, using them with #colorLiteral, or changing them for different trait collections. Unfortunately the best solution for now seems to be to not use them in IB at all.



来源:https://stackoverflow.com/questions/53583593/cant-programmatically-change-color-set-in-storyboard-as-color-from-xcassets-cat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!