swift 使用Objective-C对具有原始String类型的枚举进行编码

6ss1mwsb  于 2023-01-29  发布在  Swift
关注(0)|答案(2)|浏览(89)

我有一个可编码的枚举:

public enum MyEnum: String, Codable, Hashable, Sendable {
  case one = "ONE"
  case two = "TWO"

  public init(from decoder: Decoder) throws {
    let container = try decoder.singleValueContainer()
    let rawValue = try container.decode(RawValue.self)
    self = MyEnum(rawValue: rawValue) ?? .one
  }
}

但是,我现在需要使它与objective-c兼容。我知道我不能有一个String原始值,它必须是Int。我仍然需要它像以前一样兼容,因为它是从JSON创建的,它是一个字符串,而不是一个整数。

ozxc1zmp

ozxc1zmp1#

我建议创建一个单独的桥类型来向Obj-C公开,而不是修改纯Swift类型以将其公开给Obj-C,从而限制可以使用的语言特性。
这种方法使得使用Swift的全部功能对数据建模变得更加容易,并且一旦代码库完全迁移到Swift(或者至少是需要访问Obj-C兼容类型的所有部分),移除Obj-C兼容类型也变得更加容易。

@objc public enum MyEnumBridge: Int {
  case one
  case two
}

现在给Obj-C兼容类型添加一个扩展,从纯Swift类型初始化它:

extension MyEnumBridge {
  init(wrapped: MyEnum) {
    switch wrapped {
    case .one:
      self = .one
    case .two:
      self = .two
    }
  }
}

您可以从Obj-C类型的Swift扩展调用init,但仍然在Obj-C中存储/使用枚举。
为了将Obj-C类型转换回Swift:

extension MyEnumBridge {
  var wrapped: MyEnum {
    switch self {
    case .one:
      self = .one
    case .two:
      self = .two
    }
  }
}
edqdpe6u

edqdpe6u2#

好吧,我想我想出了一个解决办法(如果我错了,请纠正我!)

public enum MyEnum: Int, Codable, Hashable, Sendable {
  case one
  case two

  enum InternalMyEnum: String, Codable {
    case one = "ONE"
    case two = "TWO"
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.singleValueContainer()

    switch self {
    case .one:
      try container.encode(InternalMyEnum.one.rawValue)
    case .two:
      try container.encode(InternalMyEnum.two.rawValue)
    }
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.singleValueContainer()
    let rawValue = try container.decode(String.self)
    let internalMyEnum = InternalMyEnum(rawValue: rawValue) ?? .one
    switch internalVariantType {
    case .one:
      self = .one
    case .one:
      self = .one
    }
  }
}

相关问题