使 UIColor Codable - 符合协议 'Encodable'
Making UIColor Codable - conforming to protocol 'Encodable'
我在从 plist 编码和加载可转换的颜色数据时遇到困难,而这些 plist 以前可以从代码轻松加载。
在 UIColor 的扩展中,我在结构以及我的编码器和解码器中提供了有限数量的可用颜色。
extension UIColor
{
struct Words
{
static let verb = UIColor(netHex: 0xff0000)
static let noun = UIColor.blue
static let subject = UIColor(netHex: 0x0000ff)
static let object = UIColor(netHex: 0x1e5900)
static let indirectObject = UIColor(netHex: 0x369d01)
static let genitive = UIColor(netHex: 0x783f04)
static let article = UIColor(netHex: 0xff6500)
static let adjective = UIColor(netHex: 0x9900ff)
static let adverb = UIColor(netHex: 0xff00ff)
static let generic = UIColor(netHex: 0x70747a)
}
class func color(data:Data) -> UIColor? {
return try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UIColor
}
func encode() -> Data? {
return try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false)
}
}
在我的代码模型中(有效),我简单地定义了颜色的文本值:
var color1: String?
...
color1 = subject // etc
并且在一个方法中,将编码后的数据加载到数据库中:
let myColorData = myColor1.encode()
然后在集合视图 cellForItemAt indexPath 中,我可以访问颜色数据,我将其用于属性文本(未显示)。
let color1 = UIColor.color(data: cellData.color1 as! Data)
当我没有从代码加载数据,而是从 pList 加载数据时,就会出现问题。数据似乎已加载到核心数据中,但应用程序还是崩溃了,并出现错误:
- 无法将类型 'NSTaggedPointerString' (0x108cc0560) 的值转换为 'UIColor'
我认为这意味着 UIColor 没有被编码(?),尽管它似乎确实将某些东西 'blob' 加载到数据库中。
如果我遵循 和类似的建议,但我总是收到错误。
- 在 'Optional' 上引用实例方法 'encode(to:)' 要求 'UIColor' 符合 'Encodable'。
我想我需要使我的结构 Words: Codable,但我不确定这是否属实,也不确定这样做需要什么。
有人可以告诉我在这种情况下需要做什么如何使 UIColor 以我需要的方式进行编码吗?
为什么要 UIColor
额外符合 Codable
?它已经符合 NSSecureCoding
,因此默认情况下可序列化为 Data
。
即使使用您的实现,您也可以对颜色进行编码
let encoded = UIColor.Words.adverb.encode()!
并解码
let color = UIColor.color(data: encoded)
特别是在 Core Data 中,您可以使用计算属性将受支持的类型转换为不受支持的类型,反之亦然。
我对 Core Data 的建议是将颜色保存为 Int32
(十六进制表示)或(十六进制)String
这是我在 Core Data 中使用的一个实现,一个将颜色转换为十六进制字符串的扩展
extension UIColor {
private func float2String(_ float : CGFloat) -> String {
return String(format:"%02X", Int(round(float * 255)))
}
var hex : String {
var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0
getRed(&red, green: &green, blue: &blue, alpha: nil)
return "#" + float2String(red) + float2String(green) + float2String(blue)
}
convenience init(hex : String) {
let hex = hex.hasPrefix("#") ? String(hex.dropFirst()) : hex
if hex.count == 6, hex.range(of: "[^0-9A-Fa-f]", options: .regularExpression) == nil {
let chars = Array(hex)
let numbers = stride(from: 0, to: chars.count, by: 2).map() {
CGFloat(strtoul(String(chars[[=12=] ..< min([=12=] + 2, chars.count)]), nil, 16))
}
self.init(red: numbers[0] / 255, green: numbers[1] / 255, blue: numbers[2] / 255, alpha: 1.0)
} else {
self.init(white: 1.0, alpha: 1.0)
}
}
}
和 NSManagedObject
子类的相关部分
@NSManaged public var hexColor: String
var color : UIColor {
get { return UIColor(hex: hexColor) }
set { hexColor = newValue.hex }
}
我在从 plist 编码和加载可转换的颜色数据时遇到困难,而这些 plist 以前可以从代码轻松加载。
在 UIColor 的扩展中,我在结构以及我的编码器和解码器中提供了有限数量的可用颜色。
extension UIColor
{
struct Words
{
static let verb = UIColor(netHex: 0xff0000)
static let noun = UIColor.blue
static let subject = UIColor(netHex: 0x0000ff)
static let object = UIColor(netHex: 0x1e5900)
static let indirectObject = UIColor(netHex: 0x369d01)
static let genitive = UIColor(netHex: 0x783f04)
static let article = UIColor(netHex: 0xff6500)
static let adjective = UIColor(netHex: 0x9900ff)
static let adverb = UIColor(netHex: 0xff00ff)
static let generic = UIColor(netHex: 0x70747a)
}
class func color(data:Data) -> UIColor? {
return try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UIColor
}
func encode() -> Data? {
return try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false)
}
}
在我的代码模型中(有效),我简单地定义了颜色的文本值:
var color1: String?
...
color1 = subject // etc
并且在一个方法中,将编码后的数据加载到数据库中:
let myColorData = myColor1.encode()
然后在集合视图 cellForItemAt indexPath 中,我可以访问颜色数据,我将其用于属性文本(未显示)。
let color1 = UIColor.color(data: cellData.color1 as! Data)
当我没有从代码加载数据,而是从 pList 加载数据时,就会出现问题。数据似乎已加载到核心数据中,但应用程序还是崩溃了,并出现错误:
- 无法将类型 'NSTaggedPointerString' (0x108cc0560) 的值转换为 'UIColor'
我认为这意味着 UIColor 没有被编码(?),尽管它似乎确实将某些东西 'blob' 加载到数据库中。
如果我遵循
- 在 'Optional' 上引用实例方法 'encode(to:)' 要求 'UIColor' 符合 'Encodable'。
我想我需要使我的结构 Words: Codable,但我不确定这是否属实,也不确定这样做需要什么。
有人可以告诉我在这种情况下需要做什么如何使 UIColor 以我需要的方式进行编码吗?
为什么要 UIColor
额外符合 Codable
?它已经符合 NSSecureCoding
,因此默认情况下可序列化为 Data
。
即使使用您的实现,您也可以对颜色进行编码
let encoded = UIColor.Words.adverb.encode()!
并解码
let color = UIColor.color(data: encoded)
特别是在 Core Data 中,您可以使用计算属性将受支持的类型转换为不受支持的类型,反之亦然。
我对 Core Data 的建议是将颜色保存为 Int32
(十六进制表示)或(十六进制)String
这是我在 Core Data 中使用的一个实现,一个将颜色转换为十六进制字符串的扩展
extension UIColor {
private func float2String(_ float : CGFloat) -> String {
return String(format:"%02X", Int(round(float * 255)))
}
var hex : String {
var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0
getRed(&red, green: &green, blue: &blue, alpha: nil)
return "#" + float2String(red) + float2String(green) + float2String(blue)
}
convenience init(hex : String) {
let hex = hex.hasPrefix("#") ? String(hex.dropFirst()) : hex
if hex.count == 6, hex.range(of: "[^0-9A-Fa-f]", options: .regularExpression) == nil {
let chars = Array(hex)
let numbers = stride(from: 0, to: chars.count, by: 2).map() {
CGFloat(strtoul(String(chars[[=12=] ..< min([=12=] + 2, chars.count)]), nil, 16))
}
self.init(red: numbers[0] / 255, green: numbers[1] / 255, blue: numbers[2] / 255, alpha: 1.0)
} else {
self.init(white: 1.0, alpha: 1.0)
}
}
}
和 NSManagedObject
子类的相关部分
@NSManaged public var hexColor: String
var color : UIColor {
get { return UIColor(hex: hexColor) }
set { hexColor = newValue.hex }
}