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

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

当我在 Storyboard 中将某些 属性 的颜色(例如我的 UILabeltextColor)设置为在 xcassets 目录中创建为新颜色集的颜色时

然后我无法在第一次尝试时以编程方式更改此颜色:

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

...请注意,我是从数据源方法 cellForItemAt.

调用它的

破解: 我可以通过在情节提要中为从颜色选择器中选择的任何其他颜色设置这种颜色来解决这个问题,但我想知道为什么会这样。

那么,为什么会这样?

当从 Storyboard/Xib 加载 UIView subClassUITableViewCell 时,它会将 Attribute Inspector 中指定的属性应用于所有 subViews.我们有以下回调方法来知道何时从 Storyboard/Xib

加载视图
override func prepareForInterfaceBuilder() {
    super.prepareForInterfaceBuilder()        
}

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

这些方法可能是 add/remove 子视图的良好候选者,但它们不应该更新子视图的 size 或某些 attribute inspector 相关属性。更新子视图的推荐方法是当超级视图完成加载和应用所有 attribute inspector 属性并调用 layoutSubviews 时。因此,您应该对子视图应用任何外观更改。例如,

override func layoutSubviews() {
    super.layoutSubviews()

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

对于 UITableViewCell,任何实现 UITableViewDataSource 的对象也保证 delegate 方法在单元格显示之前应用任何修饰更改,因此这也是另一个好处候选人改变颜色。

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

真正的答案是这更接近于错误。在 iOS 13 中,以编程方式用任何其他颜色覆盖 IB 中的颜色资源集没有问题。

我从 iOS 12 调试会话中获取了一些日志,我在其中尝试了 OP 正在执行的操作:

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

单元格 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

在iOS13中,日志(和结果)不同:

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

单元格 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

iOS 12 将命名颜色转换为它使用的颜色 space 时似乎存在时间问题,发生在 layoutSubviews() 期间,因此试图覆盖在此之前的颜色是徒劳的。但是,iOS 13 似乎在没有翻译的情况下原生使用 UIDynamicCatalogColor,因此不存在时间问题。

Color Assets 似乎对 Xcode 整体来说有点事后才想到。祝你在整个应用程序中使用它们后重命名它们,将它们与#colorLiteral 一起使用,或为不同的特征集合更改它们,祝你好运。不幸的是,目前最好的解决方案似乎是根本不在 IB 中使用它们。