我在从 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()
然后在 Collection View cellForItemAt indexPath 中,我可以访问颜色数据,我将其用于属性文本(未显示)。
let color1 = UIColor.color(data: cellData.color1 as! Data)
当我没有从代码加载数据,而是从 pList 加载数据时,就会出现问题。数据似乎已加载到 Core Data 中,但应用程序还是崩溃了,并出现错误:
- 无法将“NSTaggedPointerString”类型的值 (0x108cc0560) 转换为“UIColor”
我认为这意味着 UIColor 没有被编码(?),尽管它似乎确实将一些“blob”加载到数据库中。
如果我听从 Make UIColor Codable 的建议, 和类似的,但我不断收到错误。
- 在“可选”上引用实例方法“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[$0 ..< min($0 + 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 }
}
关于swift - 使 UIColor Codable - 符合协议(protocol) 'Encodable',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56902318/