【问题标题】:How can encode array of CGPoint in Swift如何在 Swift 中编码 CGPoint 数组
【发布时间】:2020-11-15 10:44:19
【问题描述】:

您好,我从 here 找到了没有数组的好解决方案,可以正常工作

@propertyWrapper
struct EncodablePoint: Encodable {
    var wrappedValue: CGPoint
    enum CodingKeys: CodingKey {
        case x
        case y
    }
    func encode(to encoder: Encoder) throws {
        var c = encoder.container(keyedBy: CodingKeys.self)
        try c.encode(wrappedValue.x, forKey: .x)
        try c.encode(wrappedValue.y, forKey: .y)
    }
}
//usage:
struct Foo: Encodable {
    @EncodablePoint var pt: CGPoint = CGPoint(x: 123, y: 456)
    var other = "zxcv"
}

let foo = Foo()
let encoded = try! JSONEncoder().encode(foo)
print(String(bytes: encoded, encoding: .utf8) ?? "nil") // {"pt":{"x":123,"y":456},"other":"zxcv"}

我想要类似的数组解决方案,如果有人知道请帮助我。 我想要一些类似的东西:

@propertyWrapper
struct EncodablePointsArray: Encodable {
    var wrappedValue: [CGPoint]
    enum CodingKeys: CodingKey {
        ?????
    }
    func encode(to encoder: Encoder) throws {
        ??????
    }
}


struct Foo2: Encodable {
    @EncodablePointsArray var pt: [CGPoint] = [CGPoint]
    var other = "zxcv"
}

let foo2 = Foo2()
let encoded = try! JSONEncoder().encode(foo2)
print(String(bytes: encoded, encoding: .utf8) ?? "nil")
// I wold like output like : {"ArrayPoints“:[{„x“:1.1,“y“:1.2},{„x“:2.1,“y“:3.4}]},"other":"zxcv"}

【问题讨论】:

    标签: swift codable cgpoint


    【解决方案1】:

    您正在使用过时的信息。 [CGPoint]Codable 现在没有任何扩展。

    struct Foo2: Encodable {
      var pt: [CGPoint] = []
      var other = "zxcv"
    }
    

    如果您确实需要包装器,请发布需要它的代码。您的问题表明您不需要包装器。

    【讨论】:

    • 虽然这是真的,但这不是 OP 所要求的。编码Foo2 将得到{"pt":[[1.1,1.2],[2.1,3.4]],"other":"zxcv"}。显然 OP 要求这样的东西{"pt":[{"x":1.1,"y":1.2},{"x":2.1,"y":3.4}]},"other":"zxcv"}
    【解决方案2】:

    EncodablePoint 在这里充当CGPoint 的包装器,因此从客户端的角度来看,EncodablePoint 是具有CGPoint 属性的新类型。

    如果用作属性包装器,它的作用类似于CGPoint 的数组。但在编码后,它会将其转换为具有xy 坐标的自定义对象。

    根据你对这样一个对象解码后想要达到的结果,这里有两种选择。

    EncodablePoint的编码数组

    让我们像这样构建属性包装器

    @propertyWrapper
    struct EncodablePointArray: Encodable {
        var wrappedValue: [EncodablePoint]
    }
    

    那么包装器的客户端应该创建EncodablePoint的实例

    struct Points: Encodable {
        @EncodablePointArray var pt: [EncodablePoint] = [
            EncodablePoint(wrappedValue: CGPoint(x: 123, y: 456)),
            EncodablePoint(wrappedValue: CGPoint(x: 789, y: 123)),
            EncodablePoint(wrappedValue: CGPoint(x: 456, y: 789))
        ]
        var other = "zxcv"
    }
    

    解码会给你想要的结果

    {"pt":{"values":[{"x":123,"y":456},{"x":789,"y":123},{"x":456,"y":789}]},"other":"zxcv"}
    

    但我认为你想使用CGPoint 的数组,所以...

    CGPoint的编码数组

    如果你想这样直接使用CGPoints

    struct Points: Encodable {
        @EncodablePointArray var pt: [CGPoint] = [
            CGPoint(x: 123, y: 456),
            CGPoint(x: 789, y: 123),
            CGPoint(x: 456, y: 789)
        ]
        var other = "zxcv"
    }
    

    您必须使用CGPoints 构建您的包装器

    @propertyWrapper
    struct EncodablePointArray: Encodable {
        var wrappedValue: [CGPoint]
    }
    

    但是解码出来的String会不一样:

    {"pt":{"values":[[123,456],[789,123],[456,789]]},"other":"zxcv"}
    

    【讨论】:

      【解决方案3】:

      使用unkeyedContainer()nestedContainer(keyedBy:) 函数可以解决问题:

      @propertyWrapper
      struct EncodablePointsArray: Encodable {
          var wrappedValue: [CGPoint]
          
          enum CodingKeys: CodingKey {
              case x
              case y
          }
          
          func encode(to encoder: Encoder) throws {
              var unkeyedContainer = encoder.unkeyedContainer()
              try wrappedValue.forEach {
                  var container = unkeyedContainer.nestedContainer(keyedBy: CodingKeys.self)
                  try container.encode($0.x, forKey: .x)
                  try container.encode($0.y, forKey: .y)
              }
          }
      }
      

      以你为例:

      struct Foo2: Encodable {
          @EncodablePointsArray var pt: [CGPoint] = [CGPoint(x: 1.1, y: 1.2), CGPoint(x: 2.1, y: 3.4)]
          var other = "zxcv"
      }
      
      let foo2 = Foo2()
      do {
          let encoded = try JSONEncoder().encode(foo2)
          print(String(bytes: encoded, encoding: .utf8) ?? "nil")
      } catch {
          print(error)
      }
      

      这将导致:

      {
          "pt": [
              {
                  "x": 1.1000000000000001,
                  "y": 1.2
              },
              {
                  "x": 2.1000000000000001,
                  "y": 3.3999999999999999
              }
          ],
          "other": "zxcv"
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-18
        • 1970-01-01
        • 2017-05-22
        • 2014-08-14
        • 1970-01-01
        • 2020-05-30
        • 1970-01-01
        相关资源
        最近更新 更多