RxSwift 登录/注册/搜索/编辑/网络 Demo
final class LoginViewModel { struct Input { let username: Observable<String> let password: Observable<String> let captchaTap: ControlEvent<Void> let loginTap: ControlEvent<Void> } struct Output { let isEnabled: Driver<Bool> let captcha: Driver<(title: String, isEnabled: Bool)> let login: Driver<Bool> let state: Driver<UIState> } } extension LoginViewModel: ViewModelType { func transform(_ input: LoginViewModel.Input) -> LoginViewModel.Output { let isEnabled = input.verifyloginButton() let state = State() let captcha = input.requestLoginCaptcha(state) let login = input.requestLogin(state) return Output(isEnabled: isEnabled, captcha: captcha, login: login, state: state.asDriver(onErrorJustReturn: .idle)) } } fileprivate extension LoginViewModel.Input { func verifyloginButton() -> Driver<Bool> { return Observable .combineLatest(username.isEmpty, password.isEmpty) { !0ドル && !1ドル } .asDriver(onErrorJustReturn: false) } func requestLoginCaptcha(_ state: State) -> Driver<(title: String, isEnabled: Bool)> { return captchaTap.withLatestFrom(username) .flatMap{ LCUser.rx.requestLoginCaptcha(mobile: 0ドル) .trackState(state, success: "验证码已发送") .catchErrorJustComplete() } .flatMap(to: 60.countdown()) .asDriver(onErrorJustReturn: (title: "重新发送", isEnabled: true)) } func requestLogin(_ state: State) -> Driver<Bool> { let usernameAndPassword = Observable .combineLatest(username, password) { (username: 0ドル, password: 1ドル) } return loginTap.withLatestFrom(usernameAndPassword) .flatMap { LCUser.rx.login(mobile: 0ドル.username, captcha: 0ドル.password) .trackState(state, success: "登录成功") .catchErrorJustComplete() } .map(to: true) .asDriver(onErrorJustReturn: false) } }