我正在尝试将
Color
转换为 UIColor
。不幸的是,当 SwiftUI 颜色是动态的(浅色和深色的值不同)时,创建的 UIColor 不是动态的。
这是一些代码示例来说明问题:
let lightTraits = UITraitCollection(userInterfaceStyle: .light)
let darkTraits = UITraitCollection(userInterfaceStyle: .dark)
let uiColor = UIColor(dynamicProvider: {
$0.userInterfaceStyle == .dark ? .red : .yellow
})
uiColor.resolvedColor(with: lightTraits).hexadecimalRepresentation // #FFFF00 (== .yellow: OK)
uiColor.resolvedColor(with: darkTraits).hexadecimalRepresentation // #FF0000 (== .red: OK)
let color = Color(uiColor: uiColor)
let invalidColor = UIColor(color)
invalidColor.resolvedColor(with: lightTraits).hexadecimalRepresentation // #FFFF00 ( == .yellow: OK)
invalidColor.resolvedColor(with: darkTraits).hexadecimalRepresentation // #FFFF00 (.yellow ??)
extension UIColor {
var hexadecimalRepresentation: String? {
var r: CGFloat = 0
var g: CGFloat = 0
var b: CGFloat = 0
var a: CGFloat = 0
getRed(&r, green: &g, blue: &b, alpha: &a)
return String(format: "#%02lX%02lX%02lX", lroundf(Float(r) * 255), lroundf(Float(g) * 255), lroundf(Float(b) * 255))
}
}
我相信
UIColor(_ color: Color)
仅读取一种配色方案的颜色...
TLDR:发生这种情况的原因是
uiColor.resolvedColor(with: darkTraits)
在评估时没有对 SwiftUI.Color
应用“环境”。
您可以从
cgColor
获取某个 SwiftUI.Color
的 colorScheme
值,如下所示:
[旁注:iOS 17+!]
var env = EnvironmentValues()
env.colorScheme = .dark // or .light
let resolved = color.resolve(in: env)
print(resolved.cgColor.components)
因此,理想情况下,您将从
SwiftUI.Color
获取颜色分量,然后再将其转换为 UIColor
。或者您始终可以将 UIColor
转换回 SwiftUI.Color
。我用多层来回转换对其进行了测试。
至于为什么这不能按预期工作,这是我的猜测。
SwiftUI.Color
是View
。它不是您通常认为的意义上的“颜色”。这是一个“应该用颜色绘制的 SwiftUI 视图”。SwiftUI.View
不是可见视图。它是对应该绘制的东西的结构的声明。SwiftUI
视图的实例仅在提供环境和状态时才有意义。将你的问题放入上下文中:我们采用一个
SwiftUI.Color
,这是一个SwiftUI.View
,这是结构的定义,它需要一个环境和一个状态来表示某些东西。我们将其放入 UIColor
中,并在该环境和状态上下文之外检查/评估它。这到底是什么意思?
我们尝试通过
uiColor.resolvedColor(with: darkTraits)
模拟环境,但显然 UIColor 不会将其转换为环境。
这引导我们找到上面的解决方案:我们采用
SwiftUI.Color
并通过应用具有深色配色方案的环境来解决它。