I was wondering if it is possible to encode and decode a GeoPoint from the firebase's JSON response using standard swift 4?
It looks like as of now that the GeoPoint is not Codable?
I get the following error
No 'decode' candidates produce the expected contextual result type 'GeoPoint'
in my Codable class
final class Data: Codable
{
var location:GeoPoint = GeoPoint(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
{
located = try values.decode(Location.self, forKey: .geoloc) //error here
}
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)
}
}
I was able to extend the GeoPoint class and make it Codable. That is how I solved it.
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)
}
}
Now I can use my original Data class to consume the JSON response from Google, using my extended MyGeoPoint class (instead of Google's GeoPoint directly)
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)
}
}