Dépendance RxSwift

May 02 2023
Si vous avez utilisé RxSwift, vous connaissez cet extrait de code : pour simplifier un peu ce processus et réduire la dépendance de RxSwift à un seul endroit, je crée une classe simple en suivant ces étapes. La logique de déclenchement est à l'intérieur de la classe et vous pouvez diviser la logique en une fonction distincte.
Dépendance RxSwift

Si vous avez utilisé RxSwift, vous connaissez cet extrait de code :

var taskChangeEvent = BehaviorSubject<Bool>()
...

if newValue != oldValue {
  subject.onNext(newValue)
}

...

taskChangeEvent.subscribe(onNext: { [weak self] done in
    ....
}).dispose(by: disposeBag)

Pour rendre ce processus un peu plus simple et réduire la dépendance de RxSwift à un seul endroit, je construis une classe simple en suivant ces étapes.

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 logique de déclenchement est à l'intérieur de la classe et vous pouvez diviser la logique en une fonction distincte.

L'écoute du flux est beaucoup plus propre et il n'y a pas de dispositionBag partout dans le code.

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)
}

Remarque sur l'utilisation de BehaviorSubject

Comme vous le savez, le BehaviorSubject émet le dernier événement à qui commence à écouter. Cela pourrait être un problème, pendant la phase d'installation, car c'est comme la plomberie alors qu'il y a de l'eau dans les tuyaux. Vous êtes visité alors que vous n'êtes pas encore prêt. D'autre part, le PublishSubject vous permet de connecter des canaux ensemble, puis d'envoyer les événements.

Pensez donc à utiliser PublishSubject si vous avez besoin d'un peu de temps de préparation avant de recevoir des événements.