简体   繁体   English

无法以编程方式将情节提要中设置的颜色更改为 xcassets 目录中的颜色

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

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当我将 Storyboard 中某些属性的颜色(例如UILabel textColor )设置为在 xcassets 目录中创建为新颜色集的颜色时

在此处输入图片说明

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 . ...请注意,我是从数据源方法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. Hack:我可以通过在 Storyboard 中为从颜色选择器选择的任何其他颜色设置这种颜色来解决它,但我想知道为什么会发生这种情况。

So, why is this happening?那么,为什么会发生这种情况?

When a UIView subClass like UITableViewCell is loaded from the Storyboard/Xib , it applies the attributes specified in Attribute Inspector to all the subViews .UIView subClassUITableViewCell从加载Storyboard/Xib ,它适用于所指定的属性Attribute Inspector到所有的subViews We have the following callback methods to know when a view is loaded from the Storyboard/Xib ,我们有以下回调方法来了解何时从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.这些方法可能是添加/删除子视图的不错选择,但它们不应该更新子视图的size或一些与attribute inspector相关的属性。 The recommended method to update subViews is when the super view finishes loading and applying all the attribute inspector properties and calls layoutSubviews .更新子视图的推荐方法是当超级视图完成加载和应用所有attribute inspector属性并调用layoutSubviews So then you should apply any cosmetic change to a subView.因此,您应该将任何外观更改应用于子视图。 eg,例如,

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.对于UITableViewCell ,任何实现UITableViewDataSource对象还保证在单元格显示之前应用任何外观更改的delegate方法,如下所示,因此这也是更改颜色的另一个很好的候选者。

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

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.在 iOS 13 中,以编程方式用任何其他颜色覆盖 IB 中设置的颜色资产没有问题。

I grabbed some logs from an iOS 12 debug session where I attempted what the OP is doing:我从 iOS 12 调试会话中获取了一些日志,在那里我尝试了 OP 正在执行的操作:

Cell 1单元格 1

At awakeFromNib : UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6在awakeFromNib : UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6
Setting background color to : UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6将背景颜色设置为: UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6
At layoutSubviews : kCGColorSpaceModelRGB 0.235 0.235 0.263 0.6在 layoutSubviews : kCGColorSpaceModelRGB 0.235 0.235 0.263 0.6

Cell 2单元格 2

At awakeFromNib : UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6在awakeFromNib : UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6
Setting background color to : kCGColorSpaceModelRGB 0.490196 0.760784 0.262745 1将背景颜色设置为:kCGColorSpaceModelRGB 0.490196 0.760784 0.262745 1
At layoutSubviews : kCGColorSpaceModelRGB 0.235 0.235 0.263 0.6在 layoutSubviews : kCGColorSpaceModelRGB 0.235 0.235 0.263 0.6

In iOS 13, the logs (and the results) are different:在 iOS 13 中,日志(和结果)是不同的:

Cell 1单元格 1

At awakeFromNib : UIDynamicCatalogColor: 0x600003e83600;在awakeFromNib : UIDynamicCatalogColor: 0x600003e83600; name = My Background Color名称 = 我的背景颜色
Setting background color to : UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6将背景颜色设置为: UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6
At layoutSubviews : UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6在 layoutSubviews : UIExtendedSRGBColorSpace 0.235 0.235 0.263 0.6

Cell 2单元格 2

At awakeFromNib : UIDynamicCatalogColor: 0x600003e99290;在awakeFromNib : UIDynamicCatalogColor: 0x600003e99290; name = My Background Color名称 = 我的背景颜色
Setting background color to : UIDynamicCatalogColor: 0x600003e99020;将背景颜色设置为: UIDynamicCatalogColor: 0x600003e99020; name = Button Green名称 = 按钮绿色
At layoutSubviews : UIDynamicCatalogColor: 0x600003e99350;在 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.当 iOS 12 将命名颜色转换为它使用的颜色空间时,似乎存在时间问题,发生在layoutSubviews()期间,因此在此之前尝试覆盖颜色是徒劳的。 However, iOS 13 seems to use UIDynamicCatalogColor natively without the translation, so there is no timing issue.但是,iOS 13 似乎在没有翻译的情况下原生使用 UIDynamicCatalogColor,因此不存在计时问题。

Color Assets seem to be a bit of an afterthought for Xcode overall.颜色资产对于 Xcode 整体来说似乎有点事后诸葛亮。 Good luck renaming them after they've been used throughout your app, using them with #colorLiteral, or changing them for different trait collections.祝你在整个应用程序中使用它们后重命名它们,将它们与 #colorLiteral 一起使用,或者为不同的特征集合更改它们。 Unfortunately the best solution for now seems to be to not use them in IB at all.不幸的是,目前最好的解决方案似乎是根本不在 IB 中使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM