Search code examples
arraysswiftrx-swifturlsession

Cannot assign value of type [Employees] to type 'PublishSubject<[Employees]>


I have successfully parsed json data using URLSession and now I want to add the parsed data to an array. Doing this using an ordinary array works fine, but I'm learning Rx and thus want to use a subject.

So, this works:

var parsedJson = [Employees]()
self.parsedJson = decodedJson.people

But this gives an error:

var parsedJson: PublishSubject<[Employees]> = PublishSubject<[Employees]>()
self.parsedJson = decodedJson.people

Cannot assign value of type '[Employees]' to type 'PublishSubject<[Employees]>'

Here is the URLSession code:

//    var parsedJson = [Employees]()
    var parsedJson: PublishSubject<[Employees]> = PublishSubject<[Employees]>()


    func getJSON(completion: @escaping () -> Void) {
        guard let url = URL(string:"https://api.myjson.com/bins/jmos6") else { return }

        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data else { return }

            do {
                let jsonDecoder = JSONDecoder()
                jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase
                jsonDecoder.dateDecodingStrategy = .iso8601

                let decodedJson = try jsonDecoder.decode(People.self, from: data)
                self.parsedJson = decodedJson.people
                completion()
            } catch {
                print(error)
            }
        }.resume()
    }

Anyone know how to do this and why there is an error in the first place? Doesn't the <> simply indicate which type should be observed? Didn't get .accept() to work either.

EDIT

let parsedJson: BehaviorRelay<[Employees]> = BehaviorRelay(value: [])
self.parsedJson.accept(decodedJson.people)

This worked, but what is the equivalent to BehaviorSubject and PublishSubjuct?


Solution

  • The error message is pretty clear: you have a type-mismatch. You would get the same error message if you tried to assign a String to an Int variable, for example. A PublishSubject is not an array. Its a mechanism (think of it as a pipeline) for sending a stream of certain types of values (here an array of Employees).

    You typically use Subjects by subscribing to them like so:

    var parsedJson = PublishSubject<[Employee]>()
    // the 'next' block will fire every time an array of employees is sent through the pipeline
    parsedJson.next { [weak self] employees in
        print(employees)
    }
    

    The above next block will fire every time you send an array through the PublishSubject like so:

    let decodedJson = try jsonDecoder.decode(People.self, from: data)
    self.parsedJson.onNext(decodedJson.people)
    

    From your EDIT it seems that you moved on to trying to use a BehaviorRelay. I would recommend reading up on the differences between these two classes before decided which is appropriate for your use case. This article was really helpful to me when trying to learn the differences between the different types of Subjects and Relays: https://medium.com/@dimitriskalaitzidis/rxswift-subjects-a2c9ff32a185

    Good luck!