Кнопка включения с логикой RxSwift
Я новичок в RxSwift
и хочу добиться следующего. у меня есть email and password TextField
, Когда вы ввели текст в оба textfields
кнопка должна быть включена.
В моем ViewController я делаю следующее:
txtEmail.rx.text.asObservable()
.bindTo(viewModel.email)
.addDisposableTo(disposeBag)
txtPassword.rx.text.asObservable()
.bindTo(viewModel.password)
.addDisposableTo(disposeBag)
viewModel.buttonEnabled
.bindTo(btnLogin.rx.isEnabled)
.addDisposableTo(disposeBag)
И вот моя ViewModel:
import Foundation
import RxSwift
import RxCocoa
class LoginViewModel {
let email = Variable<String?>("")
let password = Variable<String?>("")
var buttonEnabled: Observable<Bool>
init() {
var processedEmail: Observable<String>!
var processedPassword: Observable<String>!
processedEmail = email.asObservable().map(String.toLower as! (String?) -> String).map(String.trimWhiteSpace as! (String?) -> String)
processedPassword = password.asObservable().map(String.toLower as! (String?) -> String).map(String.trimWhiteSpace as! (String?) -> String)
let emailValid = processedEmail.asObservable().map(String.isNotEmpty)
let passwordValid = processedPassword.asObservable().map(String.isNotEmpty)
buttonEnabled = Observable.combineLatest(emailValid, passwordValid) {
return $0 && $1
}
}
func didTapLoginButton() {
print("hello \(email.value)")
}
}
По какой-то причине init
метод моего viewmodel
никогда не заканчивается Кто-нибудь может мне помочь?
2 ответа
Похоже на определение processedEmail
а также processedPassword
генерируют сбой, мешающий инициализации модели представления завершиться.
Более конкретно, String.toLower
а также String.trimWhiteSpace
метод, вероятно, имеет тип (String) -> String
но здесь они насильно брошены на (String?) -> String
,
processedEmail = email.asObservable()
.map { $0 ?? "" }
.map(String.toLower)
.map(String.trimWhiteSpace)
processedPassword = password.asObservable()
.map { $0 ?? "" }
.map(String.toLower)
.map(String.trimWhiteSpace)
Я только добавил .map { $0 ?? "" }
, Поскольку исходная наблюдаемая имеет тип Observable<String?>
вызов карты преобразует его в Observable<String>
который затем будет обрабатываться String.toLower
а также String.trimWhiteSpace
Я попробовал этот пример init, и он работает:
init() {
let processedEmail = email.asObservable()
.map { $0 ?? "" }
.map { $0.lowercased() }
.map { !$0.isEmpty }
let processedPassword = password.asObservable()
.map { $0 ?? "" }
.map { $0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) }
.map { !$0.isEmpty }
buttonEnabled = Observable.combineLatest(processedEmail, processedPassword) {
return $0 && $1
}
}