未能使用协议包含采用Codable的协议

时间:2018-03-07 08:48:38

标签: ios swift xcode codable

考虑以下事项:

protocol A: Codable {
  var b: B { get }
  var num: Int { get }
}
protocol B: Codable {
  var text: String { get }
}
struct C: A {
  var b: B
  var num: Int
}

编译器提供两个错误

  • 输入' C'不符合协议' Decodable'
  • 输入' C'不符合协议' Encodable'

然而,A和B都是可编码的。如何解决/避免这些错误?

参考: Reference

EDITED

由于Codable的自动合成不起作用,我手动实现了所需的方法。

struct C: A {
  var b: B
  var num: Int

  enum CodingKeys: String, CodingKey {
    case b
    case num
  }

  func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(num, forKey: .num)
    try container.encode(b, forKey: .b)
  }
  init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    num = try values.decode(Int.self, forKey: .num)
    b = try values.decode(B.self, forKey: .b)
  }
}

现在它出现了新的错误

enter image description here

2 个答案:

答案 0 :(得分:1)

协议不告诉编译器如何编码/解码符合它的类/结构。您需要为编译器实现协议,以完全了解如何初始化C结构的实例。

struct D: B {
  var text: String
}

struct C: A {
  var b: B
  var num: Int

  public init(from decoder: Decoder) throws {
    b = D(text: " ")
    num = 0
  }

  public func encode(to encoder: Encoder) throws {

  } 
}

这是一个更完整的例子,与问题的第二部分一致。

protocol A: Codable {
  var b: B { get }
  var num: Int { get }
}
protocol B: Codable {
  var text: String { get }
}
struct D: B {
  var text: String
}

struct C: A {
  var b: B
  var num: Int

  enum CodingKeys: String, CodingKey {
    case b
    case num
  }

  public init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    num = try values.decode(Int.self, forKey: .num)
    let text = try values.decode(String.self, forKey: .b)
    b = D(text: text)
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(num, forKey: .num)
    try container.encode(b.text, forKey: .b)
  }
}

答案 1 :(得分:0)

您应该在 struct C 中实现 init(来自解码器:解码器)编码(到编码器:编码器),因为这些是必需的 Codable (可解码和可编码)协议使用。

public init(from decoder: Decoder) throws{

}

public func encode(to encoder: Encoder) throws{

} 

<强> EDITED

在Swift协议中,它不会向自己确认,因此您应该在协议A中使用 associatedtype 来确认协议B.

为了更好地理解协议,请阅读此答案。

https://stackoverflow.com/a/43408193/6303078

protocol B: Codable {
    var text: String { get }
}

protocol A: Codable {
    associatedtype CodableType : B
    var b: CodableType { get }
    var num: Int { get }
}

struct D: B {
    var text: String
}

struct C<ElementType:B> : A{

    typealias CodableType = ElementType

    var b: CodableType
    var num: Int

    enum CodingKeys: String, CodingKey {
        case b
        case num
    }

    public init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        num = try values.decode(Int.self, forKey: .num)
        b = try values.decode(CodableType.self, forKey: .b)
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(num, forKey: .num)
        try container.encode(b, forKey: .b)
    }
}