仅在 rx_tap 事件上调用方法

call method only on rx_tap event

我有一个关于 rxswift 的基本问题。 我有一个登录屏幕,当且仅当我点击登录按钮时,它应该在视图模型中调用我的登录方法

        loginButton.rx_tap
        .doOn({[unowned self] _ in
            self.loginButton.enabled = false
        })
        .flatMap({[unowned self] in self.loginModel.login() })
        .subscribeNext({ [weak self] login  in
            self?.loginButton.enabled = true

            guard login?.result == 1 else {
                self?.showErrorWithMessage(login!.message)
                return;
            }

           // Logged in!
        })
        .addDisposableTo(disposeBag)

看起来不错,但如果由于凭据无效而导致登录失败并且用户重新开始在文本字段中键入,则会再次触发对 loginModel.login() 的调用...

在视图模型中还有:

    var credentials : Driver<(String, String)> {
    return Driver.combineLatest(userNameDriver.distinctUntilChanged(), passwordDriver.distinctUntilChanged()) { usr, pwd in
        return (usr, pwd)
    }
}

var usrValid : Driver<Bool> {
    get {
        return userNameDriver
            .throttle(0.5)
            .filterEmpty()
            .distinctUntilChanged()
            .map { ([=12=].rangeOfString("@") != nil) || ([=12=].utf8.count == 0) }
    }
}

var pwdValid : Driver<Bool> {
    get {
        return passwordDriver
        .throttle(0.5)
        .filterEmpty()
        .distinctUntilChanged()
        .map { ([=12=].utf8.count > 5) || ([=12=].utf8.count == 0) }
    }
}

var usernameBorderColor : Observable<UIColor>!
var passwordBorderColor : Observable<UIColor>!

var credentialValid : Driver<Bool> {
    return Driver.combineLatest(usrValid, pwdValid) { usr, pwd in
        return (usr && pwd)
    }
}

有人可以帮我解决这个问题吗? 谢谢

我审查了你的项目。问题不是您的 ViewModel 的架构很好。我使用 RxSwift repo 中的示例修复了一个。在下面查看您的新视图模型:

class LoginViewModel
{
let validatedUsername: Driver<Bool>
let validatedPassword: Driver<Bool>

// Is login button enabled
let loginEnabled: Observable<Bool>

// Has user log in
let loggedIn: Observable<Login>

var usernameBorderColor : Observable<UIColor>
var passwordBorderColor : Observable<UIColor>

init(input: (
    userName: Driver<String>,
    password: Driver<String>,
    loginClick: Observable<Void>
    ),
    dependency: (
    RxMoyaProvider<APIProvider>
    )
    ) {

    let credentials = Driver.combineLatest(input.userName, input.password) { ([=10=], ) }

    validatedUsername = input.userName.map { [=10=].rangeOfString("@") != nil }
    validatedPassword = input.password.map { [=10=].utf8.count > 5 }

    usernameBorderColor = validatedUsername.asObservable()
        .map{valid in
            return valid ? UIColor.clearColor() : UIColor.redColor()
    }
    passwordBorderColor = validatedPassword.asObservable()
        .map{valid in
            return valid ? UIColor.clearColor() : UIColor.redColor()
    }

    loginEnabled = Observable.combineLatest(
        validatedUsername.asObservable(),
        validatedPassword.asObservable()
    )   { username, password in
        username &&
        password
        }
        .distinctUntilChanged()
        .shareReplay(1)

    loggedIn = input.loginClick.withLatestFrom(credentials)
        .flatMap { username, password -> Observable<Login> in
            var resultLogin : Login
            if username == "test@" && password == "123123" {
                resultLogin = Login(result: 1, message: "OK")
            }
            else {
                resultLogin = Login(result: 0, message: "KO")
            }

            return Observable.create { observer in
                observer.onNext(resultLogin)
                observer.onCompleted()

                return AnonymousDisposable {

                }
            }
        }
        .retry()
        .shareReplay(1)
    }
}

您还必须更改登录视图控制器:

let viewModel = LoginViewModel(
        input: (
            userName: userTextField.rx_text.asDriver(),
            password: pwdTextField.rx_text.asDriver(),
            loginClick: loginButton.rx_tap.asObservable()
        ),
        dependency: (
            apiProvider
        )
    )

    viewModel.loginEnabled
        .subscribeNext { [weak self] valid  in
            self?.loginButton.enabled = valid
            self?.loginButton.alpha = valid ? 1.0 : 0.5
        }
        .addDisposableTo(self.disposeBag)

    viewModel.loggedIn
        .subscribeNext { login  in

            print(login.message)

            guard login.result == 1 else {
                // Show error
                return;
            }


            }
        .addDisposableTo(disposeBag)

我创建了拉取请求,您必须接受它并查看完整的源代码。祝你好运!