[英]How do I emulate a computed property with access to the latest value in RxSwift?
If I want to emulate a standard property of eg a Bool
in RxSwift I can use let isValid = Variable<Bool>(false)
and then use .value
to get the last value inline and .asObservable()
to access the stream. 如果要在RxSwift中模拟
Bool
标准属性,则可以使用let isValid = Variable<Bool>(false)
,然后使用.value
内联获取最后一个值,并使用.asObservable()
访问流。
However I want to emulate a computed propery eg var isValid { return self.password.characters.count > 0 }
and also be able to get the last value inline as well as in the form of an observable stream. 但是我想模拟一个计算的属性,例如
var isValid { return self.password.characters.count > 0 }
并且还能够内联以及以可观察流的形式获取最后一个值。
I want to be able to do both so I can write code like ... 我希望能够做到这两者,所以我可以编写类似...的代码
if isValid.value { // isValid is Variable<Bool>
// ... do something ....
}
as well as bind to eg a TextField 以及绑定到例如TextField
I know I can write as a pure Observable
as follows ... 我知道我可以写成如下所示的纯
Observable
...
var isValid: Observable<Bool> {
return self.username.asObservable().map { username in // username is Variable<String>
return username.characters.count > 0
}
}
but then I have to refactor the previous example to be .... 但是然后我必须将前面的示例重构为....
isValid.subscribe { isValid in
if isValid.element {
// ... do something ....
}
}.dispose(of: self.disposeBag)
How then do I express a computed property in RxSwift which can be consumed as an inline value as well as a stream? 然后,我如何在RxSwift中表达一个计算属性,该属性可以作为内联值和流使用?
I had the same problem and ended up with a solution that does not look clean but works. 我遇到了同样的问题,最终得到的解决方案看起来不干净,但可以正常工作。 I would add a new
var valid: Bool = false
and a subscription to the isValid
observable that updates it 我将添加一个新的
var valid: Bool = false
和对isValid
observable的订阅以对其进行更新
isValid.subscribe(onNext:{ [weak self] value in self?.valid = valid}) isValid.subscribe(onNext:{self中的[weak self]值?.valid = valid})
With this isValid
is used for binding and subscriptions and valid
for use in imperative code. 使用此方法,
isValid
用于绑定和订阅,并且在命令式代码中valid
。
Btw your definition of isValid
is kind of "unnatural", just make it a let isValid: Observable<Bool>
and assign it in init
like isValid = username.asObservable().map({$0.characters.count > 0})
顺便说一句,您对
isValid
的定义有点“不自然”,只要让它成为let isValid: Observable<Bool>
并像isValid = username.asObservable().map({$0.characters.count > 0})
这样在init
分配即可isValid = username.asObservable().map({$0.characters.count > 0})
Update: 更新:
Another solution is using RxBlockling, you can get the current value with try! isValid.toBlocking().single()
另一个解决方案是使用RxBlockling,您可以
try! isValid.toBlocking().single()
使用当前值try! isValid.toBlocking().single()
try! isValid.toBlocking().single()
but I think it is a worse solution and generally not recommended. try! isValid.toBlocking().single()
但我认为这是一个较差的解决方案,通常不建议这样做。
Try this: 尝试这个:
let username = Variable("")
private let _isValid: Observable<Bool> = username.asObservable().map{ $0.characters.count > 0 }
let isValid = Variable(false)
Then, in your init
, viewDidLoad
or wherever: 然后,在您的
init
, viewDidLoad
或任何地方:
_isValid.asObservable()
.bind(to: isValid)
.disposed(by: bag)
You can test it with: 您可以使用以下方法进行测试:
isValid.asObservable()
.subscribe(onNext: {
print("value: \($0)")
})
.disposed(by: disposeBag)
username.value = "xfreire"
// OUTPUTS:
// value: false
// value: true
and you are still able to do: 而且您仍然可以执行以下操作:
if isValid.value {
// ...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.