使用 RxSwift 逻辑启用按钮

enable button with RxSwift logic

我是 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 [=11=] && 
        }

    }

    func didTapLoginButton() {
        print("hello \(email.value)")
    }
}

出于某种原因,我的 viewmodelinit 方法从未完成。 有人能帮我吗?

似乎 processedEmailprocessedPassword 的定义正在生成阻止视图模型初始化完成的崩溃。

更具体地说,String.toLowerString.trimWhiteSpace 方法可能具有类型 (String) -> String,但在这里它们被强制转换为 (String?) -> String.

processedEmail = email.asObservable()
  .map { [=10=] ?? "" }
  .map(String.toLower)
  .map(String.trimWhiteSpace)

processedPassword = password.asObservable()
  .map { [=10=] ?? "" }
  .map(String.toLower)
  .map(String.trimWhiteSpace)

我只添加了 .map { [=17=] ?? "" }。因为原始可观察对象的类型为 Observable<String?>,map 调用会将其转换为 Observable<String>,然后可由 String.toLowerString.trimWhiteSpace

处理

我尝试了这个 init 示例,它似乎有效:

init() {
    let processedEmail = email.asObservable()
        .map { [=10=] ?? "" }
        .map { [=10=].lowercased() }
        .map { ![=10=].isEmpty }

    let processedPassword = password.asObservable()
        .map { [=10=] ?? "" }
        .map { [=10=].trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) }
        .map { ![=10=].isEmpty }

    buttonEnabled = Observable.combineLatest(processedEmail, processedPassword) {
        return [=10=] && 
    }
}