【发布时间】:2018-05-29 12:22:36
【问题描述】:
我正在为结合 RxSwift 的 PublishSubject 的特定用例而苦苦挣扎。
为了简单起见,省略了不重要的细节。
有一个 MVVM 设置。在 VC 中,我有一个 UIButton,点击它应该调度网络调用。在 ViewModel 中,我有一个 buttonDidTapSubject: PublishSubject<Void>。
class ViewModel {
let disposeBag = DisposeBag()
let buttonDidTapSubject = PublishSubject<Void>()
let service: Service
typealias Credentials = (String, String)
var credentials: Observable<Credentials> {
return Observable.just(("testEmail", "testPassword"))
}
init(_ service: Service) {
self.service = service
buttonDidTapSubject
.withLatestFrom(credentials)
.flatMap(service.login) // login method has signature func login(_ creds: Credentials) -> Observable<User>
.subscribe(onNext: { user in print("Logged in \(user)") },
onError: { error in print("Received error") })
.disposed(by: disposeBag)
}
}
class ViewController: UIViewController {
let viewModel: ViewModel
let button = UIButton()
init(_ viewModel: ViewModel) {
self.viewModel = viewModel
}
}
在控制器的viewDidLoad 中我进行了绑定:
override func viewDidLoad() {
button.rx.tap.asObservable()
.subscribe(viewModel.buttonDidTapSubject)
.disposed(by: disposeBag)
}
问题是,由于网络请求可能会失败并且从login(_:) 方法返回的Observable 会产生错误,因此ViewModel 中对buttonDidTapSubject 的整个订阅将被释放。按钮上的所有其他点击都不会触发登录 ViewModel 的序列。
有什么办法可以避免这种行为吗?
【问题讨论】:
-
看看github.com/RxSwiftCommunity/Action 绑定按钮时非常有用,并且有很好的功能(比如自动处理启用状态)
标签: ios swift cocoa-touch rx-swift