本文介绍了UIColor返回深色模式颜色的错误值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义的UITextField子类,当在其中键入某些内容时,它会更改其边框颜色.我正在通过拨打电话收听更改

I have a custom UITextField subclass which changes its border color when typing something in it. I'm listening for changes by calling

self.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)

然后,在textFieldDidChange(_:)中我正在做

self.layer.borderColor = UIColor(named: "testColor")?.cgColor

其中testColor是Assets.xcassets中定义的一种颜色,具有亮和暗模式的变体.问题是UIColor(named: "testColor")?.cgColor似乎总是返回灯光模式的颜色.

Where testColor is a color defined in Assets.xcassets with variants for light and dark mode. The issue is that UIColor(named: "testColor")?.cgColor seems to always return the color for the light mode.

这是iOS 13 Beta中的错误,还是我做错了什么?有一个GitHub存储库,其中的代码可以展示这种行为.运行项目,从XCode切换到暗模式,然后开始在文本字段中输入内容.

Is this a bug in iOS 13 beta or I'm doing something wrong? There's a GitHub repo with the code which exhibits this behaviour. Run the project, switch to dark mode from XCode then start typing something in the text field.

推荐答案

简短答案

在这种情况下,您需要指定要使用哪个特征集合来解析动态颜色.

Short answer

In this situation, you need to specify which trait collection to use to resolve the dynamic color.

self.traitCollection.performAsCurrent {
    self.layer.borderColor = UIColor(named: "testColor")?.cgColor
}

self.layer.borderColor = UIColor(named: "testColor")?.resolvedColor(with: self.traitCollection).cgColor

更长的答案

在动态UIColor上调用cgColor方法时,它需要解析动态颜色的值.这是通过引用当前特征集UITraitCollection.current来完成的.

Longer answer

When you call the cgColor method on a dynamic UIColor, it needs to resolve the dynamic color's value. That is done by referring to the current trait collection, UITraitCollection.current.

当调用某些方法的重写时,UIKit会设置当前特征集合,特别是:

The current trait collection is set by UIKit when it calls your overrides of certain methods, notably:

  • UIView
    • draw()
    • layoutSubviews()
    • traitCollectionDidChange()
    • tintColorDidChange()
    • UIView
      • draw()
      • layoutSubviews()
      • traitCollectionDidChange()
      • tintColorDidChange()
      • viewWillLayoutSubviews()
      • viewDidLayoutSubviews()
      • traitCollectionDidChange()
      • containerViewWillLayoutSubviews()
      • containerViewDidLayoutSubviews()
      • traitCollectionDidChange()

      但是,在这些方法的覆盖范围之外,当前特征集不必设置为任何特定值.因此,如果您的代码未覆盖这些方法之一,并且您想解析一种动态颜色,则有责任告诉我们要使用的特征集.

      However, outside of overrides of those methods, the current trait collection is not necessarily set to any particular value. So, if your code is not in an override of one of those methods, and you want to resolve a dynamic color, it's your responsibility to tell us what trait collection to use.

      (这是因为可以覆盖任何视图或视图控制器的userInterfaceStyle特征,因此即使设备可能设置为亮模式,您也可能拥有处于暗模式的视图.)

      (That's because it's possible to override the userInterfaceStyle trait of any view or view controller, so even though the device may be set to light mode, you might have a view that's in dark mode.)

      您可以通过使用UIColor方法 resolvedColor(with:) .或使用UITraitCollection方法 performAsCurrent ,然后将可解析的代码放入瓶盖内部的颜色.上面的简短答案显示了两种方法.

      You can do that by directly resolving the dynamic color, using the UIColor method resolvedColor(with:). Or use the UITraitCollection method performAsCurrent, and put your code that resolves the color inside the closure. The short answer above shows both ways.

      您还可以将代码移入这些方法之一.在这种情况下,我认为您可以将其放在layoutSubviews()中.如果这样做,则当明暗样式更改时,它将自动被调用,因此您无需执行其他任何操作.

      You could also move your code into one of those methods. In this case, I think you could put it in layoutSubviews(). If you do that, it will automatically get called when the light/dark style changes, so you wouldn't need to do anything else.

      WWDC 2019,在iOS中实现暗模式

      从19:00开始,我讨论了动态颜色的分辨方法,然后在23:30,我举了一个示例,说明如何像您一样将CALayer的边框颜色设置为动态颜色.

      Starting at 19:00 I talked about how dynamic colors get resolved, and at 23:30 I presented an example of how to set a CALayer's border color to a dynamic color, just like you're doing.

      这篇关于UIColor返回深色模式颜色的错误值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 06:19