swift - 如何更好地结合使用相同发布主题的这两个值

标签 swift rx-swift reactive-cocoa

我正在学习RxSwift

我已经设置了一个 View 模型来响应我的 ViewController 中的绑定(bind)。

isValid 检查用户名和密码是否存在,然后启用我的登录按钮。

didTapLoginSubject 在登录时触发,使用 credentialsObservable 中的最新值将调用服务。

这一切都按照我的意愿工作,但是我觉得在 isValidcredentialsObservable 的工作方式方面有些东西还没有完全优化。

我看到重复的代码,感觉可以写得更好,但我还不知道如何写。

我想也许是这样的:

    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/

相关文章:

ios - 如何创建日期调度程序?

ios - 在我的 ReactiveCocoa 测试项目中了解 ReactiveCocoa 和 MVVM

ios - 如何阻止多个 AVAudioPlayer 快速播放?

ios - 不希望贝塞尔曲线路径被 View 框架剪切

ios - 在 Objective-C 中找不到带有 Swift 类参数的方法

ios - RxSwift - 可观察的自定义类

swift - 如何执行推送 UIViewController 或呈现 UIAlertController?

ios - 将 UITableViewCell 中的 UIButton 点击​​手势绑定(bind)到 viewModel 中的可观察对象

ios - 处理 UITableView 绑定(bind)中的连接错误(Moya、RxSwift、RxCocoa)

ios - react 迅速的新版本NSNotificationCenter