登录
BindTo方式
手机号输入页面



1、手机号输入11位时,按钮【下一步】可点击,否则灰显;
2、点击【下一步】校验输入字符是否为手机号,正确走3,否则校验失败,toast提示;
3、点击【下一步】手机号校验通过后,调用校验手机号是否已经注册API,“是”则调入【密码页面】,“否”调入【注册页面】。
model : 负责定义数据结构
struct InputMobileResult: Mapable {
var code: String?
var message: String?
init() {
}
init?(json: JSON) {
code = json["code"].stringValue
message = json["message"].stringValue
}
}
service : 负责常规校验(字段、合法性等)和API调用
class AccountService {
static let instance = AccountService()
let disposeBag = DisposeBag()
private init() {}
func validateMobile(_ mobile: String) -> CommonResult {
if mobile.count == 11 && mobile.td.isPhoneNumber() {
return .success(message:"")
} else if mobile.count > 11 {
return .failed(message:"")
} else {
return .empty
}
}
func mobileNextStep(_ mobile: String) -> Observable<InputMobileResult?> {
return APIService.rx.request(MultiTarget(UserRequest.uservalidateTelNo(tel: mobile)))
.asObservable()
.debug("Observable")
.mapResponseToObj(type: InputMobileResult.self)
}
func validatePassword(_ password: String) -> Observable<CommonResult> {
if !password.isEmpty {
return .just(.success(message:""))
} else {
return .just(.failed(message:""))
}
}
func passwordNextStep(_ mobile: String, password: String) -> Driver<InputPasswordResult?> {
return APIService.rx.request(MultiTarget(UserRequest.userlogin(imgCode: "", password: password, telno: mobile)))
.asObservable()
.debug("Observable")
.mapResponseToObj(type: InputPasswordResult.self)
.asDriver(onErrorJustReturn: InputPasswordResult(json: ["code": "-1", "message": String.td.localized("TD_Empty_Data_InternetTitle")]))
}
}
viewModel: 负责与controller通信
class InputMobileViewModel: MVVMTDPInputMobileViewModel {
let service = AccountService.instance
let mobile = Variable<String>("")
let nextTaps = PublishSubject<Void>()
let mobileUsable: Observable<CommonResult>
let nextButtonEnabled: Observable<Bool>
let nextResult: Observable<InputMobileResult?>
init() {
let service = AccountService.instance
mobileUsable = mobile.asObservable()
.map { mobile in
return service.validateMobile(mobile)
}
.share(replay: 1)
nextButtonEnabled = mobileUsable.asObservable()
.map({ (mobile) in
return mobile.isValid
})
.distinctUntilChanged()
.share(replay: 1)
let paramters = Observable.combineLatest(mobile.asObservable(), mobile.asObservable()) {
($0, $1)
}
nextResult = nextTaps.asObservable().withLatestFrom(paramters)
.flatMapLatest { (mobile, _) in
return service.mobileNextStep(mobile)
.observeOn(MainScheduler.instance)
.catchErrorJustReturn(InputMobileResult(json: ["code": "-1", "message": String.td.localized("TD_Empty_Data_InternetTitle")]))
}
.share(replay: 1)
}
}
controller:负责业务的组装
let disposeBag = DisposeBag()
let service = AccountService.instance
func rxSwiftBindTo() {
let inputViewModel = InputMobileViewModel()
mobileTextField.rx.text.orEmpty
.bind(to: inputViewModel.mobile)
.disposed(by: disposeBag)
nextBtn.rx.tap
.bind(to: inputViewModel.nextTaps)
.disposed(by: disposeBag)
inputViewModel.nextButtonEnabled
.subscribe(onNext: { [unowned self] valid in
self.nextBtn.isEnabled = valid
self.nextBtn.isUserInteractionEnabled = valid
self.nextBtn.backgroundColor = valid ? UIColor(valueRGB: 0xc8a66b) : UIColor(valueRGB: 0xc8a66b, alpha: 0.3)
})
.disposed(by: disposeBag)
inputViewModel.nextResult.subscribe(onNext: { [unowned self] result in
self.hideHub(title: nil)
if result?.code == "1" {
self.gotoInputPassword(phone: (self.mobileTextField.text!))
} else if result?.code == "0" {
self.gotoRegister(phone: (self.mobileTextField.text!))
} else {
self.errorMessageDidChange(message: (result?.message ?? "").isEmpty ? "验证失败": (result?.message!)!)
}
}).disposed(by: disposeBag)
}
Driver方式
密码输入页面
model : 负责定义数据结构
struct UserLoginModelInfo: Mapable {
var headImage: String?
var telno: String?
var token: String?
var uname: String?
var id: Int?
init?(json: JSON) {
headImage = json["headImage"].stringValue
id = json["id"].intValue
telno = json["telno"].stringValue
token = json["token"].stringValue
uname = json["uname"].stringValue
}
}
struct InputPasswordResult: Mapable {
var data: UserLoginModelInfo?
var message: String?
var code: String?
init() {
}
init?(json: JSON) {
code = json["code"].stringValue
message = json["message"].stringValue
if json["data"] != JSON.null {
data = UserLoginModelInfo.init(json: json["data"])
}
}
}
service : 负责常规校验(字段、合法性等)和API调用
class AccountService {
static let instance = AccountService()
let disposeBag = DisposeBag()
private init() {}
func validatePassword(_ password: String) -> Observable<CommonResult> {
if !password.isEmpty {
return .just(.success(message:""))
} else {
return .just(.failed(message:""))
}
}
func passwordNextStep(_ mobile: String, password: String) -> Driver<InputPasswordResult?> {
return APIService.rx.request(MultiTarget(UserRequest.userlogin(imgCode: "", password: password, telno: mobile)))
.asObservable()
.debug("Observable")
.mapResponseToObj(type: InputPasswordResult.self)
.asDriver(onErrorJustReturn: InputPasswordResult(json: ["code": "-1", "message": String.td.localized("TD_Empty_Data_InternetTitle")]))
}
}
viewModel: 负责与controller通信
class InputPasswordViewModel {
let loginButtonEnabled: Driver<Bool>
init(_ password: Driver<String>) {
loginButtonEnabled = password
.map { !$0.isEmpty }
.asDriver()
}
}
controller:负责业务的组装
let dispose = DisposeBag()
let service = AccountService.instance
func driverTo() {
let passwordViewModel = InputPasswordViewModel(passwordTextField.rx.text.orEmpty.asDriver())
passwordViewModel.loginButtonEnabled.drive(onNext: { [unowned self] valid in
self.loginBtn.isEnabled = valid
self.loginBtn.isUserInteractionEnabled = valid
self.loginBtn.backgroundColor = valid ? UIColor(valueRGB: 0xc8a66b) : UIColor(valueRGB: 0xc8a66b, alpha: 0.3)
})
.disposed(by: disposeBag)
}
func login() {
let mobile = self.getExtra("phone") as! String
self.showHub(title: nil)
self.service.passwordNextStep(mobile, password: self.passwordTextField.text!)
.drive(onNext: { [unowned self] result in
self.hideHub(title: nil)
if result?.code == "1"{
self.service.localizationUserInfo(mobile, model: result!)
} else {
self.errorMessageDidChange(message: (result?.message ?? "").isEmpty ? String.td.localized("Login_Fail") : (result?.message!)!)
}
})
.disposed(by: disposeBag)
}
注册
BindTo方式
model : 负责定义数据结构
struct UserRegisterModelResult: Mapable {
var data: UserRegisterModelData?
var message: String?
var code: String?
var uname: String?
var id: Int?
init() {
}
init?(json: JSON) {
code = json["code"].stringValue
message = json["message"].stringValue
uname = json["uname"].stringValue
id = json["id"].intValue
if json["data"] != JSON.null {
data = UserRegisterModelData(json: json["data"])
}
}
}
service : 负责常规校验(字段、合法性等)和API调用
func validateVerifyCode(_ code: String) -> CommonResult {
if !code.isEmpty {
return .success(message: "")
} else {
return .failed(message: "")
}
}
func validatePassword(_ password: String) -> CommonResult {
if password.count >= 6 && password.count <= 16 {
return .success(message: "")
} else {
return .failed(message: "")
}
}
func regsiter(_ mobile: String, vertifyCode: String, password: String) -> Observable<UserRegisterModelResult?> {
return APIService.rx.request(MultiTarget(UserRequest.registerup(tel: mobile, password: password, telCode: vertifyCode, agree: "1")))
.asObservable()
.debug("Observable")
.mapResponseToObj(type: UserRegisterModelResult.self)
}
viewModel: 负责与controller通信
class RegisterViewModel: MVVMTDRegisterViewModel {
let mobile = Variable<String>("")
let mobileCode = Variable<String>("")
let loginPwd = Variable<String>("")
let registerTaps = PublishSubject<Void>()
let sumbitDataEvent = PublishSubject<Void>()
let mobileCodeUsable: Observable<CommonResult>
let passwordUsable: Observable<CommonResult>
let registerButtonEnabled: Observable<Bool>
let registerResult: Observable<UserRegisterModelResult?>
init() {
let service = AccountService.instance
mobileCodeUsable = mobileCode.asObservable().map({ (code) in
return service.validateVerifyCode(code)
})
.share(replay: 1)
passwordUsable = loginPwd.asObservable().map({ (password) in
return service.validatePassword(password)
})
.share(replay: 1)
registerButtonEnabled = Observable.combineLatest(mobileCodeUsable, passwordUsable) { (mobileCode, loginPwd) in
return mobileCode.isValid && loginPwd.isValid
}
.distinctUntilChanged()
.share(replay: 1)
let mobileAndPassword = Observable.combineLatest(mobile.asObservable(), mobileCode.asObservable(), loginPwd.asObservable()) {
($0, $1, $2)
}
registerResult = registerTaps.asObservable().withLatestFrom(mobileAndPassword)
.flatMapLatest { (mobile, mobileCode, loginPwd) in
return service.regsiter(mobile, vertifyCode: mobileCode, password: loginPwd)
.observeOn(MainScheduler.instance)
.catchErrorJustReturn(UserRegisterModelResult(json: ["code": "-1", "message": String.td.localized("TD_Empty_Data_InternetTitle")]))
}
.share(replay: 1)
}
}
controller:负责业务的组装
let dispose = DisposeBag()
let service = AccountService.instance
let rxViewModel = RegisterViewModel()
func rxSwiftBindTo() {
let mobile = Variable<String>(self.getExtra("phone") as! String)
mobile.asObservable()
.bind(to: rxViewModel.mobile)
.disposed(by: dispose)
bgView.msgVerifyCodeTextField.rx.text.orEmpty
.bind(to: rxViewModel.mobileCode)
.disposed(by: dispose)
bgView.loginPwdTextField.rx.text.orEmpty
.bind(to: rxViewModel.loginPwd)
.disposed(by: dispose)
bgView.regBtn.rx.tap
.bind(to: rxViewModel.registerTaps)
.disposed(by: dispose)
rxViewModel.registerButtonEnabled.subscribe(onNext: { [unowned self] valid in
self.bgView.regBtn.isEnabled = valid
self.bgView.regBtn.isUserInteractionEnabled = valid
self.bgView.regBtn.alpha = valid ? 1.0 : 0.5
self.bgView.regBtn.backgroundColor = valid ? UIColor(valueRGB: 0xc8a66b) : UIColor(valueRGB: 0xc8a66b, alpha: 0.3)
})
.disposed(by: dispose)
rxViewModel.registerResult
.subscribe(onNext: { [unowned self] result in
self.hideHub(title: nil)
if result?.code == "1" {
self.service.regsiterSuccess(mobile: mobile.value, model: result!)
self.didRegister()
} else {
self.errorMessageDidChange(message: (result?.message)!)
}
})
.disposed(by: dispose)
rxViewModel.sumbitDataEvent
.flatMapLatest { _ in
self.service.regsiter((self.viewModel?.phone)!,
vertifyCode: self.bgView.msgVerifyCodeTextField.text!,
password: self.bgView.loginPwdTextField.text!)
}
.subscribe(onNext: { [unowned self] result in
self.hideHub(title: nil)
if result?.code == "1" {
self.service.regsiterSuccess(mobile: mobile.value, model: result!)
self.didRegister()
} else {
self.errorMessageDidChange(message: (result?.message)!)
}
})
.disposed(by: dispose)
}