我试图写一个扩展来满足扩展中的协议,如下所示:
extension UIColor: JSONRepresentable {
convenience init?(json: Any) {
guard let colourArray = json as? [CGFloat] else {
print("json was not an array of CGFloats")
return nil
}
self.init(red: colourArray[0],
green: colourArray[1],
blue: colourArray[2],
alpha: colourArray[3])
}
}
我收到此错误:Initializer requirement 'init(json:)' can only be satisfied by a required initializer in the definition of non-final class 'UIColor'
。如果我添加required
关键字,则会收到此错误'required' initializer must be declared directly in class 'UIColor' (not in an extension)
。是否有理由和任何解决方法?
修改:为了清楚起见,这是协议
protocol JSONRepresentable {
init?(json: Any)
}
答案 0 :(得分:4)
struct Color: Codable {
let red, green, blue, alpha: CGFloat
}
extension Color {
var uiColor: UIColor { return UIColor(color: self) }
var cgColor: CGColor { return uiColor.cgColor }
var ciColor: CIColor { return CIColor(color: uiColor) }
var data: Data { return try! JSONEncoder().encode(self) }
}
extension UIColor {
convenience init(color: Color) {
self.init(red: color.red, green: color.green, blue: color.blue, alpha: color.alpha)
}
var color: Color {
let color = CIColor(color: self)
return Color(red: color.red, green: color.green, blue: color.blue, alpha: color.alpha)
}
}
extension Data {
var string: String {
return String(data: self, encoding: .utf8) ?? ""
}
}
游乐场测试
let json = """
{"red": 0.5, "green": 0.0, "blue": 0.0, "alpha": 1.0}
"""
if let color = try? JSONDecoder().decode(Color.self, from: Data(json.utf8)) {
print(color) // "Color(red: 0.5, green: 0.0, blue: 0.0, alpha: 1.0)\n"
print(color.uiColor) // "UIExtendedSRGBColorSpace 0.5 0 0 1\n
print(color.data) // "40 bytes\n"
print(color.data.string) // "{"red":0.5,"alpha":1,"blue":0,"green":0}\n"
}
let redColor = UIColor.red.color
let jsonData = redColor.data.string // "{"red":1,"alpha":1,"blue":0,"green":0}"
如果你需要使用你的CGFloats数组,你可以覆盖JSON编码器和解码器初始化器:
extension Color {
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
red = try container.decode(CGFloat.self)
green = try container.decode(CGFloat.self)
blue = try container.decode(CGFloat.self)
alpha = try container.decode(CGFloat.self)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(red)
try container.encode(green)
try container.encode(blue)
try container.encode(alpha)
}
}
测试
let values: [CGFloat] = [0.5,0.0,0.0,1.0]
let jsonData = try JSONSerialization.data(withJSONObject: values) // 11 bytes
let json = jsonData.string // "[0.5,0,0,1]"
do {
let color = try JSONDecoder().decode(Color.self, from: jsonData)
print(color) // "Color(red: 0.5, green: 0.0, blue: 0.0, alpha: 1.0)\n"
print(color.uiColor) // "UIExtendedSRGBColorSpace 0.5 0 0 1\n
print(color.data) // "11 bytes\n"
print(color.data.string) // "[0.5,0,0,1]\n"
let encodedData = try JSONEncoder().encode(color) // 11 bytes
print(encodedData == jsonData) // true
} catch {
print(error)
}
答案 1 :(得分:-1)
在类定义中添加必需的init,如下所示:
class YourClass: ParentClass {
required init() {}
}