Неиспользованный протокол содержит протокол принятия кодируемого

Рассмотрим следующее:

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 являются кодируемыми. Как решить / избежать этих ошибок?

Ссылка: Ссылка

РЕДАКТИРОВАНИЕ

Как автосинтез для 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)
  }
}

и теперь это дает новые ошибки

2 ответа

Протокол не говорит компилятору, как кодировать / декодировать классы / структуры, которые ему соответствуют. Вам нужна реализация протокола для компилятора, чтобы полностью понять, как инициировать экземпляр структуры 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)
  }
}

Вы должны реализовать init(из decoder: Decoder) и кодировать (to encoder: Encoder) в struct C, поскольку они необходимы для использования протокола Codable (Decodable & Encodable).

public init(from decoder: Decoder) throws{

}

public func encode(to encoder: Encoder) throws{

} 

РЕДАКТИРОВАНИЕ

В Swift протокол не подтверждает себя, поэтому вы должны использовать связанный тип в протоколе A, который подтверждает протокол B.

для лучшего понимания протокола, пожалуйста, прочитайте этот ответ.

/questions/14376572/protokol-ne-sootvetstvuet-samomu-sebe/14376583#14376583

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)
    }
}
Другие вопросы по тегам