我怎样才能更好地结合使用相同发布主题的这 2 个值
How can I better combine this 2 values that consume the same Publish Subjects
我正在学习RxSwift
。
我已经设置了一个视图模型来响应我 ViewController
中的绑定。
isValid
检查用户名和密码是否存在,然后启用我的登录按钮。
didTapLoginSubject
在按下登录时触发,使用 credentialsObservable
中的最新值将调用服务。
这一切都如我所愿,但我觉得围绕 isValid
和 credentialsObservable
的工作方式还没有完全优化。
我看到重复的代码,觉得可以写得更好,但我还不确定如何写。
我想也许是这样的:
private(set) lazy var isValid: Observable<Bool> = {
return Observable.withLatestFrom(self.credentialsObservable).map { [=10=].count > 0 && .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: { [=11=].count > 0 && .count > 0 })
}()
private var credentialsObservable: Observable<(String, String)> {
return Observable.combineLatest(self.username, self.password, resultSelector: { ([=11=], ) })
}
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)
}
}
您的视图只有在某些内容发生更改时才会获得新凭据(因为 PublishSubjects
以这种方式工作)。因此,将您的凭据存储在 BehaviorSubject
中并在视图订阅视图模型时获取最新状态可能很有用。如果您为 username/password.
提供一些配置文件状态,则这是必要的
private lazy var credentials = BehaviorSubject<(String, String)?>(value: nil)
并在 init 中准备绑定:
Observable
.combineLatest(username, password){ ([=11=], ) }
.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)
我正在学习RxSwift
。
我已经设置了一个视图模型来响应我 ViewController
中的绑定。
isValid
检查用户名和密码是否存在,然后启用我的登录按钮。
didTapLoginSubject
在按下登录时触发,使用 credentialsObservable
中的最新值将调用服务。
这一切都如我所愿,但我觉得围绕 isValid
和 credentialsObservable
的工作方式还没有完全优化。
我看到重复的代码,觉得可以写得更好,但我还不确定如何写。
我想也许是这样的:
private(set) lazy var isValid: Observable<Bool> = {
return Observable.withLatestFrom(self.credentialsObservable).map { [=10=].count > 0 && .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: { [=11=].count > 0 && .count > 0 })
}()
private var credentialsObservable: Observable<(String, String)> {
return Observable.combineLatest(self.username, self.password, resultSelector: { ([=11=], ) })
}
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)
}
}
您的视图只有在某些内容发生更改时才会获得新凭据(因为 PublishSubjects
以这种方式工作)。因此,将您的凭据存储在 BehaviorSubject
中并在视图订阅视图模型时获取最新状态可能很有用。如果您为 username/password.
private lazy var credentials = BehaviorSubject<(String, String)?>(value: nil)
并在 init 中准备绑定:
Observable
.combineLatest(username, password){ ([=11=], ) }
.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)