【问题标题】:Initializer requirement 'init(json:)' can only be satisfied by a `required` initializer in the definition of non-final class 'UIColor'初始化器要求“init(json:)”只能由非最终类“UIColor”定义中的“必需”初始化器满足
【发布时间】:2018-03-13 08:25:25
【问题描述】:

我正在尝试编写一个扩展来满足扩展中的协议,如下所示:

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)
}

【问题讨论】:

  • 您使用的是哪个 swift 版本,在 Swift4 中您的代码对我来说编译得很好?虽然我不得不删除 JSONRepresentable 一致性,因为我在操场上进行测试,但这应该会有所作为
  • 我也在使用 Swift4。我刚刚阐明了协议要求。这有什么不同吗?
  • @DávidPásztor 这就是其中的关键部分。从协议实现初始化程序时,required 必须存在。
  • 对,但是当我添加它时,我得到第二个错误:'required' initializer must be declared directly in class 'UIColor' (not in an extension)。抱歉,如果问题中没有明确说明。
  • 为什么不创建一个struct Color: Codable,添加这4 个属性(红色、绿色、蓝色和alpha),然后添加一个计算属性以从中返回一个UIColor?不用从 CGFloats 数组初始化它,只需使用字典 let json = """ {"red": 1.0, "green": 0.0, "blue": 0.0, "alpha": 1.0} """

标签: swift protocols


【解决方案1】:

代码我收到的消息是 (Swift 5.0)

Initializer requirement 'init(json:)' can only be satisfied by a 'required' initializer in non-final class 'MyColor'

尝试替换

extension UIColor: JSONRepresentable

class MyColor: UIColor, JSONRepresentable

,我有同样的信息。

这意味着MyColor类不能被扩展'as this',但是如果你使用提到的required关键字,所有的子类都必须实现这个初始化器。

例如,将 final 添加到类 (=> final class MyColor: UIColor, JSONRepresentable) 您可以忘记“required”初始值设定项,因为您明确提到永远不会有“MyColor”的子类。 很好,这是协议的原则,可以(对其他开发人员,但对您)说某些功能是否需要。

【讨论】:

    【解决方案2】:
    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}"
    


    如果您需要使用 CGFloat 数组,您可以覆盖 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)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-22
      • 2014-08-21
      • 1970-01-01
      相关资源
      最近更新 更多