【问题标题】:Swift 4 Codable in protocol with enum property具有枚举属性的协议中的 Swift 4 可编码
【发布时间】:2018-05-14 18:00:12
【问题描述】:

我有这个协议,

protocol PaginableItem {
   var resultType: ResultType { get set }
}

具有枚举类型的单个属性,

enum ResultType: String, Codable {
   case photo = "PHOTO"
   case baseItem = "BASEITEM"
   case new = "NEW"
}

我还有 3 个不同的结构和类符合 PaginableItem 和一个类有一些 PaginableItems

final class TimelineModel: Codable {
   let stream: String
   let participants: String
   let header1: PaginableList
   let header2: PaginableList
   let items: PaginableList
}

final class PaginableList: Codable {
   let data: [PaginableItem]
   let pagination: Pagination
}

我正在尝试使用 Swift 4 Codable 缓存 TimelineModel,但我不确定最好的方法。 Xcode 抱怨 PaginableItem 不符合 Codable

ResultType中必须实现init(from decoder: Decoder) throwsencode(to encoder: Encoder) throws

必须PaginableItem 也实现Codable 吗?

【问题讨论】:

  • 能否在PaginableList中添加Pagination项的声明

标签: swift enums swift4 codable


【解决方案1】:

PaginableItem 不能符合 Codable 是因为 Swift 协议不能符合自己。

来源:

Protocol doesn't conform to itself?

Encode/Decode Array of Types conforming to protocol with JSONEncoder

按照上面的第二个链接,如果您想对PaginableItem 进行编码/解码,您必须在AnyPaginableItem 类/结构中键入擦除它们并使其符合Encodable/Decodable。我已经这样做了:

protocol PaginableItem {
    var resultType: ResultType { get set }
}

class AnyPaginableItem: Codable {
    var resultType: ResultType

    init(resultType: ResultType) {
        self.resultType = resultType
    }
}

enum ResultType: String, Codable {
    case photo = "PHOTO"
    case baseItem = "BASEITEM"
    case new = "NEW"
}

struct ContainsPaginableItem: Codable {
    let paginableItem: AnyPaginableItem
}

let paginableItem = AnyPaginableItem(resultType: .photo)
let itemToEncode = ContainsPaginableItem(paginableItem: paginableItem)

let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(itemToEncode)
let jsonString = String(data: jsonData, encoding: .utf8)

这个例子只对可以在PaginableItem 中声明的属性进行编码,我认为这就是你所需要的。

如果您需要对符合PaginableItem 的类型的所有属性进行编码,您可以在上面的第二个链接中采用更长的解决方案。

【讨论】:

  • 第二个链接的“更长的解决方案”完美!非常感谢
【解决方案2】:

PaginableItem 也必须实现 Codable 吗?

绝对!通过确保 PaginableItem 符合 Codable,您可以保持对 PaginableList 的 Codable 的整体一致性。

我注意到您的 ResultType 符合 Codable。但是,如果 PaginableItem 添加另一个没有的对象会发生什么 - 可能是危险的。

【讨论】:

  • 我将协议Codable 添加到PaginableItem,但尝试编码主要TimelineModel 时Xcode 崩溃:fatal error: Array<PaginableItem> does not conform to Encodable because PaginableItem does not conform to Encodable.
  • 您可能想尝试打破对 Encodable/Decodable 协议的一致性——而不是对整个事情都遵循 Codable,而是为 Encodable 创建一个扩展,为 Decodable 创建另一个扩展
  • class Item: PaginableItem { let resultType: ResultType init(resultType: ResultType) { self.resultType = resultType } enum CodingKeys: String, CodingKey { //... } } extension Item: Encodable { func编码(到编码器:编码器)抛出 { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(resultType, forKey: .resultType) } }
  • 不是针对协议,而是针对类/结构,它们可以。
  • 是否可以将 PaginableItem 更改为结构,然后使其符合?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2014-11-09
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 2018-09-16
相关资源
最近更新 更多