因此,我在ViewController
内有一个连接到ViewModel
的按钮,并且每当轻按该按钮时,我在协调器中导航到另一个屏幕。代码是这样的:
VC
btnShowShopsMap.rx.tap
.bind(to: viewModel.selectShowMap)
VM
let selectShowMap: AnyObserver<Void>
let showShopMap: Observable<Void>
//Inside init
let _selectShowMap = PublishSubject<Void>()
selectShowMap = _selectShowMap.asObserver()
showShopMap = _selectShowMap.asObservable()
Coordinator
viewModel.showShopMap
.subscribe(onNext: { _ in self.showShopMap()})
.disposed(by: userShopVC.disposeBag)
是否可以重构以上代码?除了使用PublishSubject
之外,还有其他方法可以使用PublishSubject
我的VC,VM和协调器流程
Coordinator
func showLoginScreen(logout: Bool = false) {
guard let viewController = LoginViewController.instantiate(storyboard: .main) else { return }
viewController.viewModelFactory = { inputs in
let viewModel = LoginViewModel(inputs: inputs)
viewModel.showHome
.subscribe(onNext: { isLogged in
if isLogged {
self.showHomeScreen()
}
})
.disposed(by: viewController.disposeBag)
inputs.showOnboarding
.subscribe(onNext: { _ in
self.showOnboardingScreen()
})
.disposed(by: viewController.disposeBag)
return viewModel
}
navController.pushViewController(viewController, animated: true)
VC
var viewModelFactory: (LoginViewModel.UIInputs) -> LoginViewModel = { _ in fatalError("factory not set")}
let inputs = LoginViewModel.UIInputs(userNumber: txtUserNumber.rx.text.orEmpty.asDriver(),
password: txtPassword.rx.text.orEmpty.asDriver(),
loginTapped: btnLogin.rx.tap.asSignal(),
userNumberLostFocus: txtUserNumber.rx.controlEvent(.editingDidEnd).asSignal(),
passwordLostFocus: txtPassword.rx.controlEvent(.editingDidEnd).asSignal(),
indicator: indicator,
showOnboarding: btnShowOnboarding.rx.tap.asObservable())
VM
struct UIInputs {
let userNumber: Driver<String>
let password: Driver<String>
let loginTapped: Signal<Void>
let userNumberLostFocus: Signal<Void>
let passwordLostFocus: Signal<Void>
let indicator: ActivityIndicator
let showOnboarding: Observable<Void>
}
init(inputs: UIInputs) {}
答案 0 :(得分:1)
假设视图控制器拥有并实例化视图模型,则可以将tap控制事件作为可观察对象传递给视图模型初始化程序,然后将其公开为可观察对象,以供协调器订阅:
// VC:
let viewModel = ViewModel(..., showShopMap: btnShowShopMap.rx.tap.asObservable())
// VM:
let showShopMap: Observable<Void>
init(..., showShopMap: Observable<Void>) {
self.showShopMap = showShopMap
}
我尽量不使用主题,而只公开传递过来的变换的可观察物。
答案 1 :(得分:0)
我发现了一种非常简单的方法来解决问题并避免使用Subject
,因为VM中没有与我的按钮相关的逻辑,所以我不需要通过使用Observable
或使用Subject
。相反,我像这样直接在协调器中访问我的按钮:
viewController.btnShowOnboarding.rx.tap
.subscribe(onNext: { _ in
self.showOnboardingScreen()
})
.disposed(by: viewController.disposeBag)