การพึ่งพา RxSwift

May 02 2023
หากคุณเคยใช้ RxSwift คุณจะคุ้นเคยกับข้อมูลโค้ดนี้: เพื่อให้กระบวนการนี้ง่ายขึ้นเล็กน้อยและลดการพึ่งพา RxSwift ไปที่เดียว ฉันสร้างคลาสง่ายๆ เพียงทำตามขั้นตอนเหล่านี้ ตรรกะของการยิงอยู่ในคลาสและคุณสามารถแบ่งตรรกะออกเป็นฟังก์ชันแยกต่างหาก
การพึ่งพา RxSwift

หากคุณเคยใช้ RxSwift คุณจะคุ้นเคยกับข้อมูลโค้ดนี้:

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

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

...

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

เพื่อให้กระบวนการนี้ง่ายขึ้นเล็กน้อยและลดการพึ่งพา RxSwift ไปที่เดียว ฉันสร้างคลาสง่ายๆ เพียงทำตามขั้นตอนเหล่านี้

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

ตรรกะของการยิงอยู่ในคลาสและคุณสามารถแบ่งตรรกะออกเป็นฟังก์ชันแยกต่างหาก

การฟังสตรีมนั้นสะอาดกว่ามาก และไม่มี disposeBag ทั่วโค้ด

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

หมายเหตุด้านข้างเกี่ยวกับการใช้ BehaviorSubject

อย่างที่คุณทราบ BehaviorSubject จะออกเหตุการณ์สุดท้ายที่เริ่มฟัง นี่อาจเป็นปัญหาได้ในระหว่างขั้นตอนการติดตั้ง เพราะมันเหมือนกับการต่อท่อประปาขณะที่มีน้ำอยู่ในท่อ คุณได้รับการเยี่ยมชมในขณะที่คุณยังไม่พร้อม ในทางกลับกัน PublishSubject ให้คุณเชื่อมต่อไพพ์เข้าด้วยกันแล้วส่งเหตุการณ์

ดังนั้น ลองใช้ PublishSubject หากคุณต้องการเวลาเตรียมตัวก่อนรับกิจกรรม