如何使用Swift将UIColor转换为字符串和字符串转换为UIColor?

17

我有一个带有UIColor属性的对象:

class Beer: NSObject {
  var color: UIColor?
  ...
}

我将这个属性保存到数据库中,因此我需要将其转换为有效的JSON类型,所以我考虑将其转换为字符串。我该如何将其转换为字符串以进行存储,然后在使用该字符串创建UIColor时如何加载?


你可以将UIColor转换为十六进制颜色代码,然后将其存储在数据库中,以便在检索时直接使用该代码或将其转换为UIColor。 - HardikDG
最好将rgb和alpha组件存储为浮点值。查看此链接->https://dev59.com/PWAg5IYBdhLWcg3wOo1Q - Mihriban Minaz
你们两个中有没有人介意写一个完整的答案? - JJJ
8个回答

17

我已经提供了一些示例,但你仍然可以找到许多转换代码。

对于从UIColor转换为十六进制字符串,您可以使用以下代码:

extension UIColor {
    var rgbComponents:(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
        var r:CGFloat = 0
        var g:CGFloat = 0
        var b:CGFloat = 0
        var a:CGFloat = 0
        if getRed(&r, green: &g, blue: &b, alpha: &a) {
            return (r,g,b,a)
        }
        return (0,0,0,0)
    }
    // hue, saturation, brightness and alpha components from UIColor**
    var hsbComponents:(hue: CGFloat, saturation: CGFloat, brightness: CGFloat, alpha: CGFloat) {
        var hue:CGFloat = 0
        var saturation:CGFloat = 0
        var brightness:CGFloat = 0
        var alpha:CGFloat = 0
        if getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha){
            return (hue,saturation,brightness,alpha)
        }
        return (0,0,0,0)
    }
    var htmlRGBColor:String {
        return String(format: "#%02x%02x%02x", Int(rgbComponents.red * 255), Int(rgbComponents.green * 255),Int(rgbComponents.blue * 255))
    }
    var htmlRGBaColor:String {
        return String(format: "#%02x%02x%02x%02x", Int(rgbComponents.red * 255), Int(rgbComponents.green * 255),Int(rgbComponents.blue * 255),Int(rgbComponents.alpha * 255) )
    }
}

使用示例:

let myColorBlack = UIColor.blackColor().webColor         //#000000ff
let myLghtGrayColor = UIColor.lightGrayColor().webColor  //#aaaaaaff
let myDarkGrayColor = UIColor.darkGrayColor().webColor 

了解更多信息请查看:https://dev59.com/DIjca4cB1Zd3GeqPsivH#28697136
https://gist.github.com/yannickl/16f0ed38f0698d9a8ae7

您可以将此字符串存储在数据库中,并在需要时检索它。

从 HexString 到 UIColor

extension UIColor {
    public convenience init?(hexString: String) {
        let r, g, b, a: CGFloat

        if hexString.hasPrefix("#") {
            let start = hexString.startIndex.advancedBy(1)
            let hexColor = hexString.substringFromIndex(start)

            if hexColor.characters.count == 8 {
                let scanner = NSScanner(string: hexColor)
                var hexNumber: UInt64 = 0

                if scanner.scanHexLongLong(&hexNumber) {
                    r = CGFloat((hexNumber & 0xff000000) >> 24) / 255
                    g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255
                    b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255
                    a = CGFloat(hexNumber & 0x000000ff) / 255

                    self.init(red: r, green: g, blue: b, alpha: a)
                    return
                }
            }
        }

        return nil
    }
}

使用方法:UIColor(hexString: "#ffe700ff")

参考资料:https://www.hackingwithswift.com/example-code/uicolor/how-to-convert-a-hex-color-to-a-uicolor
https://github.com/yeahdongcn/UIColor-Hex-Swift
https://gist.github.com/arshad/de147c42d7b3063ef7bc


看起来这不太准确。我的颜色是#EAEDFF,但color.htmlRGBColor等于#EAECFE - Viktor Sec
抱歉提供外部链接,但这个链接似乎很精确:https://cocoacasts.com/from-hex-to-uicolor-and-back-in-swift - Viktor Sec

5

以下是更新内容:

  1. Swift 5.0
  2. UIKit-n-SwiftUI架构的组合
  3. #RRGGBBAA / #RRGGBB颜色值

__

import UIKit
import SwiftUI

extension Color {

    init?(hexString: String) {

        let rgbaData = getrgbaData(hexString: hexString)

        if(rgbaData != nil){

            self.init(
                        .sRGB,
                        red:     Double(rgbaData!.r),
                        green:   Double(rgbaData!.g),
                        blue:    Double(rgbaData!.b),
                        opacity: Double(rgbaData!.a)
                    )
            return
        }
        return nil
    }
}

extension UIColor {

    public convenience init?(hexString: String) {

        let rgbaData = getrgbaData(hexString: hexString)

        if(rgbaData != nil){
            self.init(
                        red:   rgbaData!.r,
                        green: rgbaData!.g,
                        blue:  rgbaData!.b,
                        alpha: rgbaData!.a)
            return
        }
        return nil
    }
}

private func getrgbaData(hexString: String) -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat)? {

    var rgbaData : (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat)? = nil

    if hexString.hasPrefix("#") {

        let start = hexString.index(hexString.startIndex, offsetBy: 1)
        let hexColor = String(hexString[start...]) // Swift 4

        let scanner = Scanner(string: hexColor)
        var hexNumber: UInt64 = 0

        if scanner.scanHexInt64(&hexNumber) {

            rgbaData = { // start of a closure expression that returns a Vehicle
                switch hexColor.count {
                case 8:

                    return ( r: CGFloat((hexNumber & 0xff000000) >> 24) / 255,
                             g: CGFloat((hexNumber & 0x00ff0000) >> 16) / 255,
                             b: CGFloat((hexNumber & 0x0000ff00) >> 8)  / 255,
                             a: CGFloat( hexNumber & 0x000000ff)        / 255
                           )
                case 6:

                    return ( r: CGFloat((hexNumber & 0xff0000) >> 16) / 255,
                             g: CGFloat((hexNumber & 0x00ff00) >> 8)  / 255,
                             b: CGFloat((hexNumber & 0x0000ff))       / 255,
                             a: 1.0
                           )
                default:
                    return nil
                }
            }()

        }
    }

    return rgbaData
}

4

使用NSCoding进行简短处理:

public extension UIColor{

    var codedString: String?{
        do{
            let data = try NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: true)

            return data.base64EncodedString()

        }
        catch let error{
            print("Error converting color to coded string: \(error)")
            return nil
        }
    }


    static func color(withCodedString string: String) -> UIColor?{
        guard let data = Data(base64Encoded: string) else{
            return nil
        }

        return try? NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: data)

    }
}

这种方法对我来说比其他提出的解决方案更可靠,因为其他方法无法正确转换某些颜色。谢谢! - cdf1982

2
受 @HardikDG 代码启发,以下是简单的Objective C函数:
- (NSString *) colorToString:(UIColor *) color {
    CGFloat red, green, blue, alpha;
    [color getRed:&red green:&green blue:&blue alpha:&alpha];
    return [NSString stringWithFormat:@"%02x%02x%02x", (int)(red * 255), (int)(green * 255) , (int)(blue * 255)];
}

- (UIColor *) stringToColor:(NSString *) color {
    if([color length] != 6) {
        return nil;
    }

    NSScanner *scanner = [NSScanner scannerWithString:color];
    UInt64 hexNumber = 0;
    if ([scanner scanHexLongLong:&hexNumber]) {
        CGFloat r = ((hexNumber & 0xff000000) >> 24) / 255.0;
        CGFloat g = ((hexNumber & 0x00ff0000) >> 16) / 255.0;
        CGFloat b = ((hexNumber & 0x0000ff00) >> 8) / 255.0;
        CGFloat a = (hexNumber & 0x000000ff) / 255.0;

        return [UIColor colorWithRed:r green:g blue:b alpha:a];
    }

    return [UIColor whiteColor];
}

1

我添加了自己的扩展,希望你喜欢:

extension UIColor {

    func toRGBAString(uppercased: Bool = true) -> String {
        var r: CGFloat = 0
        var g: CGFloat = 0
        var b: CGFloat = 0
        var a: CGFloat = 0
        self.getRed(&r, green: &g, blue: &b, alpha: &a)
        let rgba = [r, g, b, a].map { $0 * 255 }.reduce("", { $0 + String(format: "%02x", Int($1)) })
        return uppercased ? rgba.uppercased() : rgba
    }

}

1
你可以使用这个函数。
func returnUIColor(components: String) -> UIColor {
    let scanner = Scanner(string: components)
    let skipped = CharacterSet(charactersIn: "[], ")
    let comma = CharacterSet(charactersIn: ",")
    scanner.charactersToBeSkipped = skipped

    var r, g, b, a : NSString?

    scanner.scanUpToCharacters(from: comma, into: &r)
    scanner.scanUpToCharacters(from: comma, into: &g)
    scanner.scanUpToCharacters(from: comma, into: &b)
    scanner.scanUpToCharacters(from: comma, into: &a)

    let defaultColor = UIColor.lightGray

    guard let rUnwrapped = r else { return defaultColor }
    guard let gUnwrapped = g else { return defaultColor }
    guard let bUnwrapped = b else { return defaultColor }
    guard let aUnwrapped = a else { return defaultColor }

    let rfloat = CGFloat(rUnwrapped.doubleValue)
    let gfloat = CGFloat(gUnwrapped.doubleValue)
    let bfloat = CGFloat(bUnwrapped.doubleValue)
    let afloat = CGFloat(aUnwrapped.doubleValue)

    let newUIColor = UIColor(red: rfloat, green: gfloat, blue: bfloat, alpha: afloat)
    return newUIColor
}

0

Swift 3.0 IOS 10.x 不明白为什么这么复杂,这个可以用...我一定漏掉了什么...仔细阅读,从第1项开始而不是第0项。

 // convert color to string
 let color = userInfo["color"] as! UIColor       
 let diyColor = String(describing: color)

 // convert string back to color
 let diyValues = diyColor.components(separatedBy: " ")
 print("diyValues \(diyValues)")
        let returnedColor = UIColor(colorLiteralRed: diyValues[1].FloatValue()!, green: diyValues[2].FloatValue()!, blue: diyValues[3].FloatValue()!, alpha: diyValues[4].FloatValue()!)

使用这个扩展也...

extension String {

func FloatValue() -> Float? {
    guard let doubleValue = Double(self) else {
        return nil
    }

    return Float(doubleValue)
}
}

0
使用下面的UIColor扩展将字符串转换为颜色,反之亦然。
extension UIColor {


//Convert RGBA String to UIColor object
//"rgbaString" must be separated by space "0.5 0.6 0.7 1.0" 50% of Red 60% of Green 70% of Blue Alpha 100%
public convenience init?(rgbaString : String){
    self.init(ciColor: CIColor(string: rgbaString))
}

//Convert UIColor to RGBA String
func toRGBAString()-> String {

    var r: CGFloat = 0
    var g: CGFloat = 0
    var b: CGFloat = 0
    var a: CGFloat = 0
    self.getRed(&r, green: &g, blue: &b, alpha: &a)
    return "\(r) \(g) \(b) \(a)"

}
//return UIColor from Hexadecimal Color string
public convenience init?(hexaDecimalString: String) {

        let r, g, b, a: CGFloat

        if hexaDecimalString.hasPrefix("#") {
            let start = hexaDecimalString.index(hexaDecimalString.startIndex, offsetBy: 1)
            let hexColor = hexaDecimalString.substring(from: start)

            if hexColor.characters.count == 8 {
                let scanner = Scanner(string: hexColor)
                var hexNumber: UInt64 = 0

                if scanner.scanHexInt64(&hexNumber) {
                    r = CGFloat((hexNumber & 0xff000000) >> 24) / 255
                    g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255
                    b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255
                    a = CGFloat(hexNumber & 0x000000ff) / 255
                    self.init(red: r, green: g, blue: b, alpha: a)
                    return
                }
            }
        }

        return nil
    }
// Convert UIColor to Hexadecimal String
func toHexString() -> String {
    var r: CGFloat = 0
    var g: CGFloat = 0
    var b: CGFloat = 0
    var a: CGFloat = 0
    self.getRed(&r, green: &g, blue: &b, alpha: &a)
    return String(
        format: "%02X%02X%02X",
        Int(r * 0xff),
        Int(g * 0xff),
        Int(b * 0xff)
    )
}

}

将这个颜色字符串(stringWhite)保存到数据库中

let stringWhite =  UIColor.white.toHexString()

当从数据库读取颜色字符串时,请使用以下代码将 stringWhite 转换为 UIColor

let whiteColor = UIColor(hexaDecimalString: stringWhite)

2
就像许多其他答案一样,这似乎是复制的,尽管在计算过程中获取了alpha值,但您并没有支持alpha值。 - Womble

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接