Мне удалось расширить класс GeoPoint и сделать его кодируемым. Вот как я это решил.
import UIKit
final class MyGeoPoint: GeoPoint, Codable
{
override init(latitude: Double, longitude: Double)
{
super.init(latitude: latitude, longitude: longitude)
}
private enum CodingKeys: String, CodingKey
{
case latitude = "_latitude"
case longitude = "_longitude"
}
init(from decoder: Decoder) throws
{
let container = try decoder.container(keyedBy: CodingKeys.self)
var lat:Double = 0
var lon:Double = 0
do
{
lat = try container.decode(Double.self, forKey: .latitude)
}
catch
{
print("no latitude for MyGeoPoint")
}
do
{
lon = try container.decode(Double.self, forKey: .longitude)
}
catch
{
print("no longitude for MyGeoPoint")
}
super.init(latitude: lat, longitude: lon)
}
func encode(to encoder: Encoder) throws
{
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(latitude, forKey: .latitude)
try container.encode(longitude, forKey: .longitude)
}
}
Теперь я могу использовать свой исходный класс Data для получения ответа JSON от Google, используя мой расширенный класс MyGeoPoint (вместо Google GeoPoint напрямую)
final class Data: Codable
{
var location:MyGeoPoint = MyGeoPoint(latitude:0,longitude:0)
private enum CodingKeys: String, CodingKey
{
case geoloc
}
init(from decoder: Decoder) throws
{
let values = try decoder.container(keyedBy: CodingKeys.self)
do
{
//no error here anymore
location = try values.decode(MyGeoPoint.self, forKey: .geoloc)
}
catch
{
print("data has location in server response\n")
}
}
func encode(to encoder: Encoder) throws
{
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(location, forKey: .geoloc)
}
}