Dependencia de RxSwift

Si ha utilizado RxSwift, entonces está familiarizado con este fragmento de código:
var taskChangeEvent = BehaviorSubject<Bool>()
...
if newValue != oldValue {
subject.onNext(newValue)
}
...
taskChangeEvent.subscribe(onNext: { [weak self] done in
....
}).dispose(by: disposeBag)
Para simplificar un poco este proceso y reducir la dependencia de RxSwift a un solo lugar, creo una clase simple siguiendo estos pasos.
import RxSwift
class EventSerializer<T: Equatable> {
private var disposeBag = DisposeBag()
fileprivate let contactPoint: BehaviorSubject<T>
var value: T
func send(_ newValue: T) {
contactPoint.onNext(newValue)
self.value = newValue
}
func sendValueIf(_ newValue: T, compareWith: (_ oldValue: T, _ newValue: T) -> Bool) {
if compareWith(self.value, newValue) {
contactPoint.onNext(newValue)
self.value = newValue
}
}
func listen(onChange: @escaping ((T) -> Void)) {
contactPoint.subscribe( onNext: { value in
onChange(value)
}).disposed(by: disposeBag)
}
init(defaultValue: T, contactPoint: BehaviorSubject<T>? = nil) {
self.contactPoint = contactPoint ?? BehaviorSubject<T>(value: defaultValue)
self.value = defaultValue
}
}
La lógica de disparar está dentro de la clase y puede dividir la lógica en una función separada.
Escuchar la transmisión es mucho más limpio y no hay disposeBag en todo el código.
var task = EventSerilizer<Bool>(defaultValue: false)
...
func shouldInformTaskChange(_ oldValue: Bool, _ newValue: Bool) {
oldValue != newValue
}
task.sendValueIf(true, compareWith: shouldInforTaskChange)
...
task.listen { [weak self] value in
....
}
func listenToCombineLatest<E: Equatable>(with otherSerializer: EventSerializer<E>, onChange: @escaping ((T, E) -> Void)) {
Observable.combineLatest(self.contactPoint, otherSerializer.contactPoint).subscribe(onNext: { tValue, eValue in
onChange(tValue, eValue)
}).disposed(by: disposeBag)
}
Una nota al margen sobre el uso de BehaviorSubject
Como sabes, el BehaviorSubject emite el último evento a quien comienza a escuchar. Esto podría ser un problema, durante la fase de configuración, ya que es como si estuviera haciendo cañerías mientras hay agua en las tuberías. Te visitan mientras aún no estás listo. Por otro lado, PublishSubject le permite conectar tuberías y luego envía los eventos.
Así que considere usar PublishSubject si necesita algo de tiempo de preparación antes de recibir eventos.