Неиспользованный протокол содержит протокол принятия кодируемого
Рассмотрим следующее:
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)
}
}