I am trying to use 2 publishers and have them stream to 1 publisher that is mapped from both values.
My code is:
class ViewModel {
let email = CurrentValueSubject<String, Never>("")
lazy var isEmailValid = email.map { self.validateEmail(email: $0) }
let password = CurrentValueSubject<String, Never>("")
lazy var isPasswordCorrect = password.map {
self.validatePassword(password: $0)
}
let canLogin: CurrentValueSubject<Bool, Never>
private func validateEmail(email: String) -> Bool {
return email == "[email protected]"
}
private func validatePassword(password: String) -> Bool {
return password == "1234"
}
init() {
canLogin = Publishers
.CombineLatest(isEmailValid, isPasswordCorrect)
.map { $0 && $1 }
}
}
Then in the init I get this error:
//error: Cannot assign value of type
'Publishers.Map<Publishers.CombineLatest<Publishers.Map<CurrentValueSubject<String, Never>,
Bool>, Publishers.Map<CurrentValueSubject<String, Never>, Bool>>, Bool>' to type 'CurrentValueSubject<Bool, Never>'
I am new to combine so I find it a little confusing. How should I achieve, from the code above, the combination of 2 publishers isEmailValid and isPasswordCorrect, into 1 publisher that is a CurrentValueSubject<Bool, Never>?
A CurrentValueSubject is:
A subject that wraps a single value and publishes a new element whenever the value changes.
Your canLogin is certainly not a CurrentValueSubject. It is the result of combining two other publishers with the CombineLatest operator, and then mapping the combined publisher to yet another publisher.
In the language of the Swift type system, this kind of publisher is called:
Publishers.Map<Publishers.CombineLatest<Publishers.Map<CurrentValueSubject<String, Never>, Bool>, Publishers.Map<CurrentValueSubject<String, Never>, Bool>>, Bool>
Obviously, no one would declare a property with a type like that, so we use eraseToAnyPublisher to get ourselves an AnyPublisher, to say that we don't actually care what type of publisher it is.
let canLogin: AnyPublisher<Bool, Never>
...
canLogin = Publishers
.CombineLatest(isEmailValid, isPasswordCorrect)
.map { $0 && $1 }
.eraseToAnyPublisher()
You've declared the type of canLogin completely incorrectly.
It needs to be an AnyPublisher, which you can get by simply calling eraseToAnyPublisher on the map.
lazy var canLogin: AnyPublisher<Bool, Never> = isEmailValid.combineLatest(isPasswordCorrect).map { $0 && $1 }.eraseToAnyPublisher()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With