如何通过访问RxSwift中的最新值来模拟计算属性?

时间:2017-10-11 14:21:15

标签: swift observable rx-swift

如果我想在RxSwift中模拟例如Bool的标准属性,我可以使用let isValid = Variable<Bool>(false),然后使用.value获取内联的最后一个值,并.asObservable()访问流。

但是我想模仿一个计算机,例如var isValid { return self.password.characters.count > 0 }并且还能够以内联以及可观察流的形式获取最后一个值。

我希望能够做到这两点,所以我可以写代码......

if isValid.value { // isValid is Variable<Bool>
    // ... do something ....
}

以及绑定到例如一个TextField

我知道我可以写成纯Observable如下......

var isValid: Observable<Bool> {
    return self.username.asObservable().map { username in   // username is Variable<String>
        return username.characters.count > 0
    }
}

然后我必须重构前面的例子....

isValid.subscribe { isValid in 
    if isValid.element {
        // ... do something ....
    }
}.dispose(of: self.disposeBag)

那么我如何在RxSwift中表达一个计算属性,它可以作为内联值和流使用?

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,最终找到了一个看起来不干净但有效的解决方案。我会添加一个新的var valid: Bool = false和一个订阅isValid observable来更新它

isValid.subscribe(onNext:{[self self] value in self?.valid = valid})

使用此isValid用于绑定和订阅,valid用于命令式代码。

顺便说一下,您对isValid的定义有点“不自然”,只需将其设为let isValid: Observable<Bool>,然后将其分配到init,如isValid = username.asObservable().map({$0.characters.count > 0})

更新

另一个解决方案是使用RxBlockling,您可以使用try! isValid.toBlocking().single()获取当前值,但我认为这是一个更糟糕的解决方案,通常不推荐。

答案 1 :(得分:0)

试试这个:

let username = Variable("")

private let _isValid: Observable<Bool> = username.asObservable().map{ $0.characters.count > 0 }

let isValid = Variable(false)

然后,在initviewDidLoad或任何地方:

_isValid.asObservable()
    .bind(to: isValid)
    .disposed(by: bag)

您可以使用以下方法进行测试:

isValid.asObservable()
    .subscribe(onNext: {
        print("value: \($0)")

    })
    .disposed(by: disposeBag)

username.value = "xfreire"

// OUTPUTS:
// value: false
// value: true

你仍然可以这样做:

if isValid.value {
    // ...
}