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.
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.
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
I know I can write as a pure Observable
as follows ...
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?
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
isValid.subscribe(onNext:{ [weak self] value in self?.valid = valid})
With this isValid
is used for binding and subscriptions and valid
for use in imperative code.
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})
Update:
Another solution is using RxBlockling, you can get the current value with try! isValid.toBlocking().single()
try! isValid.toBlocking().single()
but I think it is a worse solution and generally not recommended.
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:
_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 {
// ...
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.