Search code examples
jsonprotocolsswift4rx-swiftdecodable

Using swift 4 Decodable protocol with RxSwift


I was recently trying to parse JSON to a model using Decodable protocol, and I have done that successfully. But now I want to implement bi-directional binding using RxSwift. For that I need to declare variables of type 'Variable<>'.Here is a snippet from my model:

struct Person : Decodable
{
    var batchcomplete = String()
    var `continue` = Continue()
    var query = Query()
    var limits = Limit()

    enum CodingKeys: String,CodingKey
    {
        case batchcomplete
        case `continue`
        case limits
        case query
    }

    init(from decoder: Decoder) throws
    {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        batchcomplete = try container.decode(String.self, forKey: .batchcomplete)
        `continue` = try container.decode(Continue.self, forKey: .`continue`)
        limits = try container.decode(Limit.self, forKey: .limits)
        query = try container.decode(Query.self, forKey: .query)
    }
}

Now if I change my 'batchcomplete' from String() to Variable,the init() method throws an error:

No 'decode' candidates produce the expected contextual result type 'Variable<String>'.

Make these changes and you will get the error.

var batchcomplete = Variable<String>("")
batchcomplete = try container.decode(Variable<String>.self, forKey: .batchcomplete)

Solution

  • Don't try to decode to a Variable ... just set its value:

    batchcomplete.value = try container.decode(String.self, forKey: .batchcomplete)
    

    Or you could also declare your instance variable and initialise it once in your init:

    let batchcomplete: Variable<String>
    batchcomplete = Variable<String>(try container.decode(String.self, forKey: .batchcomplete))
    

    On a side note, your Variable should be declared as a constant (let) because you change the value contained inside the Variable.