RxSwift 踩坑

最近在写一个纯Swift的个人项目,使用了RxSwift这个函数式编程库,
踩了一些坑,写下备用。

1. Variable & combineLatest
        var variablePayers: Variable>!

        override func viewDidLoad() {
            super.viewDidLoad()
            //1. 检查输入金额是否正确
            let moneyValid = paymentAmountInput.rx.text.orEmpty
                .map { $0.tcz_isValidMoney() }
                .shareReplay(1)

            //2. 检查输入字符串长度
            let payNameValid = payItemNameInput.rx.text.orEmpty
                .map { $0.characters.count > 0 }
                .shareReplay(1)

            //3. 检查付款人数组
            //variablePayers = Variable(payers)
            //let payersValid = variablePayers.asObservable()
            //    .map { $0.count > 0 }
            //    .shareReplay(1)
            let payersValid = Variable(payers).asObservable()
                .map { $0.count > 0 }
                .shareReplay(1)

            //4. 合并检查所有条件是否都符合
            let everythingValid = Observable.combineLatest(moneyValid, payNameValid, payersValid) { $0 && $1 && $2 }
            everythingValid
                .bindTo(addPaymentButton.rx.isEnabled)
                .addDisposableTo(disposeBag)
        }

上面代码的执行结果是everythingValid始终为true,debug后发现payersValid的状态是completed,而combineLatest函数只要发现其中一个信号是completed的,就直接为true了。那么为什么payersValid的状态不对呢?问题就出在Variable上,查看文档,描述如下

    /// Variable is a wrapper for `BehaviorSubject`.
    ///
    /// Unlike `BehaviorSubject` it can't terminate with error, and when variable is deallocated
    /// it will complete it's observable sequence (`asObservable`).

原因就是Variable被释放后,会complete它的观察者队列。

查看代码

let payersValid = Variable(payers).asObservable()
     .map { $0.count > 0 }
     .shareReplay(1)

Variable(payers)的生命周期到viewDidLoad()后就结束了,这就是为什么payersValid的状态是completed的原因。

使用上面注释的代码段3,就可以解决这个问题。

你可能感兴趣的:(RxSwift 踩坑)