#swift #codable #cgpoint
#swift #codable #cgpoint
Вопрос:
Привет, я нашел хорошее решение без массива отсюда, работает нормально
@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"}
Ответ №1:
Вы уходите от устаревшей информации. [CGPoint]
теперь Codable
без каких-либо расширений.
struct Foo2: Encodable {
var pt: [CGPoint] = []
var other = "zxcv"
}
Если вам действительно нужна оболочка, пожалуйста, опубликуйте код, который ее требует. Ваш вопрос предполагает, что вам не нужна оболочка.
Комментарии:
1. Хотя это правда, это не то, что запрашивает 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
свойством.
При использовании в качестве оболочки свойства он действует как array of CGPoint
. Но после кодирования он превращает его в пользовательский объект с x
y
координатами и .
В зависимости от результатов, которых вы хотите достичь после декодирования такого объекта, здесь есть два варианта.
Кодирование массива 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
Если вы хотите использовать CGPoint
s напрямую, как это
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"
}
Вы должны создать свою оболочку с CGPoint
помощью s
@propertyWrapper
struct EncodablePointArray: Encodable {
var wrappedValue: [CGPoint]
}
Но декодированная строка будет другой:
{"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"
}