0

I created a model and used codable with it. I am currently using GMSPath to get path, but on adding to the model class, I get the error Type 'EstimateResponse' does not conform to protocol 'Decodable' and Type 'EstimateResponse' does not conform to protocol 'Encodable'

below is my Model

class EstimateResponse: Codable {

    var path: GMSPath? // Set by Google directions API call
    var destination: String?
    var distance: String?
}

any help is appreciated

King
  • 1,885
  • 3
  • 27
  • 84

1 Answers1

0

GMSPath has an encodedPath property (which is a string), and it can also be initialised with an encoded path. You just need to encode your GMSPath to its encoded path representation.

Conform EstimateResponse to Codable with explicit implementations:

class EstimateResponse : Codable {
    var path: GMSPath?
    var destination: String?
    var distance: String?

    enum CodingKeys: CodingKey {
        case path, destination, distance
    }
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let encodedPath = try container.decode(String.self, forKey: .path)
        path = GMSPath(fromEncodedPath: encodedPath)
        destination = try container.decode(String.self, forKey: .destination)
        distance = try container.decode(String.self, forKey: .distance)
    }

    func encode(to encoder: Encoder) throws {
        var container = try encoder.container(keyedBy: CodingKeys.self)
        try container.encode(path?.encodedPath(), forKey: .path)
        try container.encode(destination, forKey: .destination)
        try container.encode(distance, forKey: .distance)
    }
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • This gave a few errors `Argument type '() -> String' does not conform to expected type 'Encodable'` `A non-failable initializer cannot delegate to failable initializer 'init(fromEncodedPath:)' written with 'init?'` `Designated initializer cannot be declared in an extension of 'GMSPath'; did you mean this to be a convenience initializer?` – King Sep 19 '19 at 16:17
  • This is another error `Initializer requirement 'init(from:)' can only be satisfied by a 'required' initializer in the definition of non-final class 'GMSPath'` – King Sep 19 '19 at 16:30
  • @King Just do what the error says. Add the word `required`. – Sweeper Sep 19 '19 at 16:32
  • WHere @Sweeper? – King Sep 19 '19 at 16:33
  • `'required' initializer must be declared directly in class 'GMSPath' (not in an extension)` – King Sep 19 '19 at 16:34
  • Obviously `GMSPath` cannot be extended with required initializers. – vadian Sep 19 '19 at 16:36
  • @vadian my thoughts too. but what do you suggest going forward? – King Sep 19 '19 at 16:37
  • @King Alternatively, manually conform `EstimateResponse` to `Codable`. See the edit. – Sweeper Sep 19 '19 at 16:41
  • @Sweeper is this line intentional as it shouldnot be `try container.encode(path?.encodedPath(), forKey: .encodedPath)` – King Sep 19 '19 at 16:43
  • @vadian can you provide an answer as per your explanation. It would definately help – King Sep 19 '19 at 16:44
  • encode `Reference to member 'encodedPath' cannot be resolved without a contextual type` – King Sep 19 '19 at 16:45
  • @King Sweeper's solution is better than the conversion to `[CLLocationCooordinate2D]` – vadian Sep 19 '19 at 16:46
  • Thanks @Sweeper. This works. Could there be a work around as if the model contains a lot of values. it would not be convenient to write doing keys for everything – King Sep 19 '19 at 17:02
  • @King I don't know of any. However, if you only need to encode the data, you can conform `GMSPath` and `EstimateResponse` to `Encodable`, and use the solution I presented before. Since it's just `Encodable`, you won't have trouble with the initialiser. – Sweeper Sep 19 '19 at 17:05