尝试将SwiftUI颜色更改为UIColor的实例。
我可以轻松地从UIColor获取RGBA,但是我不知道如何获取“ Color”实例以返回相应的RGB和不透明度值。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void input_store(int* in_file_len, FILE* input_file);
int main(int argc, char* argv[])
{
//store files into variables
FILE* input_file = fopen(argv[1], "r");//descriptions to be added
//count the entire input_file
if(input_file == NULL)
{
printf("failed");
return 0;
}
int in_file_len;
input_store(&in_file_len, input_file);
fclose(input_file);
}
void input_store(int* in_file_len, FILE* input_file)
{
in_file_len = 0;
char ch = getc(input_file);
printf("%c\n", ch);
while(ch != EOF)
{
if(ch == '\n')
{
in_file_len++;
}
ch = getc(input_file);
}
printf("%d\n", *in_file_len); // here
}
...或者也许有更好的方法来完成我想要的。
答案 0 :(得分:24)
现在有一个新的初始化程序,它需要一个Color
并为 iOS 返回一个UIColor
,或者为 macOS 返回一个NSColor
。所以:
UIColor(Color.red)
NSColor(Color.red)
UIColor(Color.red).cgColor /* For iOS */
NSColor(Color.red).cgColor /* For macOS */
如果您正在寻找颜色成分,可以找到我有用的扩展名here in this answer
答案 1 :(得分:5)
该解决方案如何?
extension Color {
func uiColor() -> UIColor {
let components = self.components()
return UIColor(red: components.r, green: components.g, blue: components.b, alpha: components.a)
}
private func components() -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {
let scanner = Scanner(string: self.description.trimmingCharacters(in: CharacterSet.alphanumerics.inverted))
var hexNumber: UInt64 = 0
var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0
let result = scanner.scanHexInt64(&hexNumber)
if result {
r = CGFloat((hexNumber & 0xff000000) >> 24) / 255
g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255
b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255
a = CGFloat(hexNumber & 0x000000ff) / 255
}
return (r, g, b, a)
}
}
用法:
let uiColor = myColor.uiColor()
这有点骇人听闻,但这至少是一件事情,直到我们得到一个有效的方法为止。这里的键是self.description
,它给出颜色的十六进制描述(如果不是动态的,我应该添加)。剩下的只是获取颜色分量并创建UIColor
的计算。
答案 2 :(得分:1)
这不是SwiftUI的工作方式。您正在尝试做的非常类似于UIKit。在SwiftUI中,您很少询问任何参数的视图。目前,Color
没有任何返回其RGB值的方法或属性。而且我怀疑会不会存在。
通常,使用SwiftUI,您需要转到源代码,即首先用于创建颜色的变量。例如:
let r = 0.9
let g = 0.4
let b = 0.7
let mycolor = Color(red: r, green: g, b, opacity: o)
没有类似的内容
let green = mycolor.greenComponent()
相反,您需要检查变量g
(用于创建颜色的变量):
let green = g
我知道这听起来很奇怪,但这就是框架的设计方式。可能要花一些时间才能使用它,但最终您会这么做。
您可能会问,但是如果mycolor创建为:
let mycolor = Color.red
在这种情况下,您很不走运:-(
答案 3 :(得分:1)
@turingtested更新了您的答案以摆脱长时间的元组崩溃。
extension Color {
func uiColor() -> UIColor {
if #available(iOS 14.0, *) {
return UIColor(self)
}
let scanner = Scanner(string: description.trimmingCharacters(in: CharacterSet.alphanumerics.inverted))
var hexNumber: UInt64 = 0
var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0
let result = scanner.scanHexInt64(&hexNumber)
if result {
r = CGFloat((hexNumber & 0xFF000000) >> 24) / 255
g = CGFloat((hexNumber & 0x00FF0000) >> 16) / 255
b = CGFloat((hexNumber & 0x0000FF00) >> 8) / 255
a = CGFloat(hexNumber & 0x000000FF) / 255
}
return UIColor(red: r, green: g, blue: b, alpha: a)
}
}
答案 4 :(得分:0)
上面的解决方案对我不起作用,所以我自己尝试了类似的方法:
extension Color {
var uiColor: UIColor {
let values = description.split(separator: " ")
if values.count == 5 {
return UIColor(red: CGFloat(Double(values[1]) ?? 1), green: CGFloat(Double(values[2]) ?? 1), blue: CGFloat(Double(values[3]) ?? 1), alpha: CGFloat(Double(values[4]) ?? 1))
}
return UIColor(red: 1, green: 1, blue: 1, alpha: 1)
}
}
您可以像这样使用它:
let colour = myColor.uiColor
颜色的描述将所有值包含在字符串中,例如:
"kCGColorSpaceModelRGB 0.509804 0.584314 0.686275 1"
我将其拆分,尝试将值转换为Double,然后转换为CGFloat,如果转换失败,我将1用作每个数字的后备。
我添加了if语句,因为该方法不适用于Color.pink之类的系统颜色,因为它们的描述只是它们的名称。您可以手动捕获这些情况,也可以像我一样忽略它们,而只返回白色。
答案 5 :(得分:0)
当前,SwiftUI API中没有直接提供此功能。但是,我设法使用了调试打印和dump
进行了临时初始化。我发现所有其他解决方案都无法说明从名称,捆绑,Color
颜色空间,.displayP3
,静态系统UIColor
初始化的Color
或不透明度发生变化的任何颜色。我的解决方案解决了上述所有问题。
extension UIColor {
convenience init?(color: Color) {
var description = ""
debugPrint(color, to: &description)
let mirror = Mirror(reflecting: color)
var internalType = "\(type(of: mirror.children.first!.value))".replacingOccurrences(of: "ColorBox<(.+)>", with: "$1", options: .regularExpression)
var opacity: CGFloat?
if internalType == "OpacityColor" {
let regex = try! NSRegularExpression(pattern: #"(\d+% )"#)
let opacityLayerCount = regex.numberOfMatches(in: description, options: [], range: NSRange(description.startIndex..<description.endIndex, in: description))
var dumpStr = ""
dump(color, to: &dumpStr)
dumpStr = dumpStr.replacingOccurrences(of: #"^(?:.*\n){\#(4 * opacityLayerCount)}.*?base: "#, with: "", options: .regularExpression)
description = String(dumpStr.prefix { !$0.isNewline })
do {
let regex = try! NSRegularExpression(pattern: #"^.*\n.*ColorBox<.*?([A-Za-z0-9]+)>"#)
let matches = regex.matches(in: dumpStr, options: [], range: NSRange(dumpStr.startIndex..<dumpStr.endIndex, in: dumpStr))
guard let match = matches.first, matches.count == 1, match.numberOfRanges == 2 else { return nil }
internalType = String(dumpStr[Range(match.range(at: 1), in: dumpStr)!])
}
do {
opacity = dumpStr.split(separator: "\n")
.suffix(2)
.lazy
.map { $0.replacingOccurrences(of: #"\s+-\s+opacity: "#, with: "", options: .regularExpression) }
.map { CGFloat(Double($0)!) }
.reduce(1, *)
}
}
switch internalType {
case "SystemColorType":
let uiColor: UIColor
switch description {
case "clear": uiColor = UIColor.clear
case "black": uiColor = UIColor.black
case "white": uiColor = UIColor.white
case "gray": uiColor = UIColor.systemGray
case "red": uiColor = UIColor.systemRed
case "green": uiColor = UIColor.systemGreen
case "blue": uiColor = UIColor.systemBlue
case "orange": uiColor = UIColor.systemOrange
case "yellow": uiColor = UIColor.systemYellow
case "pink": uiColor = UIColor.systemPink
case "purple": uiColor = UIColor.systemPurple
case "primary": uiColor = UIColor.label
case "secondary": uiColor = UIColor.secondaryLabel
default: return nil
}
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
self.init(red: r, green: g, blue: b, alpha: a * (opacity ?? 1))
case "_Resolved":
if description.range(of: "^#[0-9A-F]{8}$", options: .regularExpression) != nil {
let r = CGFloat(Int(String(description[description.index(description.startIndex, offsetBy: 1)...description.index(description.startIndex, offsetBy: 2)]), radix: 16)! / 255)
let g = CGFloat(Int(String(description[description.index(description.startIndex, offsetBy: 3)...description.index(description.startIndex, offsetBy: 4)]), radix: 16)! / 255)
let b = CGFloat(Int(String(description[description.index(description.startIndex, offsetBy: 5)...description.index(description.startIndex, offsetBy: 6)]), radix: 16)! / 255)
let a = CGFloat(Int(String(description[description.index(description.startIndex, offsetBy: 7)...description.index(description.startIndex, offsetBy: 8)]), radix: 16)! / 255)
let colorSpace = CGColorSpace(name: CGColorSpace.linearSRGB)!
let components = [r, g, b, a]
let cgColor = CGColor(colorSpace: colorSpace, components: components)!
if let opacity = opacity {
let uiColor = UIColor(cgColor: cgColor).withAlphaComponent(opacity)
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
self.init(red: r, green: g, blue: b, alpha: a)
} else {
self.init(cgColor: cgColor)
}
} else {
return nil
}
case "UIColor":
let sections = description.split(separator: " ").map { String($0) }
guard sections.count == 5 else { fatalError() }
let colorSpace = sections[0]
let r = CGFloat(Double(sections[1])!)
let g = CGFloat(Double(sections[2])!)
let b = CGFloat(Double(sections[3])!)
let a = CGFloat(Double(sections[4])!)
if colorSpace == "UIExtendedSRGBColorSpace" {
self.init(red: r, green: g, blue: b, alpha: a)
} else if colorSpace == "kCGColorSpaceModelRGB" {
let colorSpace = CGColorSpace(name: CGColorSpace.linearSRGB)!
let components = [r, g, b, a]
let cgColor = CGColor(colorSpace: colorSpace, components: components)!
self.init(cgColor: cgColor)
} else {
return nil
}
case "DisplayP3":
let regex = try! NSRegularExpression(pattern: #"^DisplayP3\(red: (-?\d+(?:\.\d+)?), green: (-?\d+(?:\.\d+)?), blue: (-?\d+(?:\.\d+)?), opacity: (-?\d+(?:\.\d+)?))"#)
let matches = regex.matches(in: description, options: [], range: NSRange(description.startIndex..<description.endIndex, in: description))
if let match = matches.first, matches.count == 1, match.numberOfRanges == 4 {
let components = (1...4).map { CGFloat(Double(String(description[Range(match.range(at: $0), in: description)!]))!)}
let (r, g, b, a) = (components[0], components[1], components[2], components[3])
if let opacity = opacity {
let uiColor = UIColor(displayP3Red: r, green: g, blue: b, alpha: a).withAlphaComponent(opacity)
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
self.init(red: r, green: g, blue: b, alpha: a)
} else {
self.init(displayP3Red: r, green: g, blue: b, alpha: a)
}
} else {
return nil
}
case "NamedColor":
if description.range(of: #"^NamedColor\(name: ".*", bundle: nil\)$"#, options: .regularExpression) != nil {
let regex = try! NSRegularExpression(pattern: #"^NamedColor\(name: "(.*)", bundle: nil\)$"#)
let matches = regex.matches(in: description, options: [], range: NSRange(description.startIndex..<description.endIndex, in: description))
if let match = matches.first {
let name = String(description[Range(match.range(at: 1), in: description)!])
if let opacity = opacity {
guard let uiColor = UIColor(named: name)?.withAlphaComponent(opacity) else { return nil }
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
self.init(red: r, green: g, blue: b, alpha: a)
} else {
self.init(named: name)
}
break
} else {
return nil
}
}
let regex = try! NSRegularExpression(pattern: #"^NamedColor\(name: "(.*)", bundle: .*NSBundle <(.*)>.*\)$"#)
let matches = regex.matches(in: description, options: [], range: NSRange(description.startIndex..<description.endIndex, in: description))
if let match = matches.first, matches.count == 1, match.numberOfRanges == 3 {
let name = String(description[Range(match.range(at: 1), in: description)!])
let path = String(description[Range(match.range(at: 2), in: description)!])
if let opacity = opacity {
guard let uiColor = UIColor(named: name, in: Bundle(path: path), compatibleWith: nil)?.withAlphaComponent(opacity) else { return nil }
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
self.init(red: r, green: g, blue: b, alpha: a)
} else {
self.init(named: name, in: Bundle(path: path), compatibleWith: nil)
}
} else {
return nil
}
default:
return nil
}
}
}
注意:虽然这不是针对当前问题的长期解决方案,但它取决于Color
的实现细节,该细节可能会在在某些情况下,它应该可以在大多数(即使不是全部)颜色中使用。