我正在学习RxSwift
。
我已经设置了一个 View 模型来响应我的 ViewController
中的绑定(bind)。
isValid
检查用户名和密码是否存在,然后启用我的登录按钮。
didTapLoginSubject
在登录时触发,使用 credentialsObservable
中的最新值将调用服务。
这一切都按照我的意愿工作,但是我觉得在 isValid
和 credentialsObservable
的工作方式方面有些东西还没有完全优化。
我看到重复的代码,感觉可以写得更好,但我还不知道如何写。
我想也许是这样的:
private(set) lazy var isValid: Observable<Bool> = {
return Observable.withLatestFrom(self.credentialsObservable).map { $0.count > 0 && $1.count > 0 }
}()
但这显然行不通。
import Foundation
import RxSwift
import RxCocoa
class LoginViewModel: NSObject {
private(set) lazy var username = PublishSubject<String>()
private(set) lazy var password = PublishSubject<String>()
private(set) lazy var didTapLoginSubject = PublishSubject<Void>()
private(set) lazy var isValid: Observable<Bool> = {
return Observable.combineLatest(self.username, self.password, resultSelector: { $0.count > 0 && $1.count > 0 })
}()
private var credentialsObservable: Observable<(String, String)> {
return Observable.combineLatest(self.username, self.password, resultSelector: { ($0, $1) })
}
private let disposeBag = DisposeBag()
override init() {
super.init()
didTapLoginSubject
.withLatestFrom(credentialsObservable)
.subscribe(
onNext: login,
onError: onError
).disposed(by: disposeBag)
}
private func login(_ username: String, _ password: String) {
print(username, password)
}
private func onError(_ error: Error) {
print(error.localizedDescription)
}
}
最佳答案
仅当某些内容发生更改时,您的 View 才会获得新的凭据(因为PublishSubjects
以这种方式工作)。因此,将您的凭据存储在 BehaviorSubject 中并在 View 订阅 View 模型时获取最新状态可能会很有用。如果您为用户名/密码提供一些配置文件状态,则这是必要的。
private lazy var credentials = BehaviorSubject<(String, String)?>(value: nil)
并在 init 中准备绑定(bind):
Observable
.combineLatest(username, password){ ($0, $1) }
.bind(to: credentials)
.disposed(by: disposeBag)
您还可以使用存储的凭据进行 isValid
检查和 didTapLoginSubject
:
var isValid: Observable<Bool> {
return credentials
.asObservable()
.map({ (credentials) -> Bool in
guard let credentials = credentials else {
return false
}
return credentials.0.count > 0 && credentials.1.count > 0
})
.distinctUntilChanged()
}
didTapLoginSubject
.withLatestFrom(credentials)
.filterNil()
.subscribe(
onNext: login,
onError: onError
).disposed(by: disposeBag)
关于swift - 如何更好地结合使用相同发布主题的这两个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57297515/