Search code examples
iosswiftreactive-programmingrx-swiftcombine

Mutable observable object in RxSwift or Combine


What I'm trying to achieve is to have a mutable Array in viewModel that can also be observed by Controller and reload tableView when its value changes. I tried to use BehaviorRelay but looks like it's immutable. I can't delete and insert data inside it's value. The best thing I managed to write is this custom ObservableObject class:

final class CustomObservableObject<T> {

var value: T {
    didSet {
        listener?(value)
    }
}

init(value: T) {
    self.value = value
}

var listener: ((T) -> Void)?

func bind(listener: @escaping ((T) -> Void)) {
    self.listener = listener
}

}

which works exactly how I want. Is there anything I can use in the Combine or RxSwift framework like this class?

Thanks in advance


Solution

  • A BehaviorRelay is built for the specific purpose of storing state and allowing you to imperatively update it which is what you are asking for.

    The BehaviorRelay type is a wrapper around the BehaviorSubject type and provides a different interface, one that does not allow the internal subject to emit an error or completed event. The Element contained in the BehaviorSubject is mutable. However, in order to mutate it you must first extract it into a var with value and then push the updated value back in with accept(_:). This will help ensure that no mutations are missed and allows you to batch up multiple mutations into a single update. These are things missing in the class you wrote.

    Please always remember though:

    Subjects [and Relays] provide a convenient way to poke around Rx, however they are not recommended for day to day use. -- Introduction to Rx

    As you learn more about, and grow more comfortable with, the reactive paradigm you will find yourself reaching for this particular crutch less often.