Mar*_*ina 9 ios swift rx-swift
我有2个UITextField属性和1个UIButton的授权控制器.我想将View绑定到ViewModel,但不知道如何操作.这是我的AuthorizatioVC.swift:
class AuthorizationViewController: UIViewController {
let disposeBag = DisposeBag()
@IBOutlet weak var passwordTxtField: UITextField!
@IBOutlet weak var loginTxtField: UITextField!
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
addBindsToViewModel()
}
func addBindsToViewModel(){
let authModel = AuthorizationViewModel(authClient: AuthClient())
authModel.login.asObservable().bindTo(passwordTxtField.rx_text).addDisposableTo(self.disposeBag)
authModel.password.asObservable().bindTo(loginTxtField.rx_text).addDisposableTo(self.disposeBag)
//HOW TO BIND button.rx_tap here?
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的AuthorizationViewModel.swift:
final class AuthorizationViewModel{
private let disposeBag = DisposeBag()
//input
//HOW TO DEFINE THE PROPERTY WHICH WILL BE BINDED TO RX_TAP FROM THE BUTTON IN VIEW???
let authEvent = ???
let login = Variable<String>("")
let password = Variable<String>("")
//output
private let authModel: Observable<Auth>
init(authClient: AuthClient){
let authModel = authEvent.asObservable()
.flatMap({ (v) -> Observable<Auth> in
return authClient.authObservable(String(self.login.value), mergedHash: String(self.password.value))
.map({ (authResponse) -> Auth in
return self.convertAuthResponseToAuthModel(authResponse)
})
})
}
func convertAuthResponseToAuthModel(authResponse: AuthResponse) -> Auth{
var authModel = Auth()
authModel.token = authResponse.token
return authModel
}
}
Run Code Online (Sandbox Code Playgroud)
joe*_*ern 15
您可以将UIButton上的水龙头转换为Observable,并将其与UITextFields中的两个Observable一起交给ViewModel.
这是您的方案的一个小工作示例.(我使用了一个小的auth客户端模拟类来模拟来自服务的响应):
ViewController:
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let loginTxtField = UITextField(frame: CGRect(x: 20, y: 50, width: 200, height: 40))
let passwordTxtField = UITextField(frame: CGRect(x: 20, y: 110, width: 200, height: 40))
let loginButton = UIButton(type: .RoundedRect)
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1)
loginTxtField.backgroundColor = UIColor.whiteColor()
view.addSubview(loginTxtField)
passwordTxtField.backgroundColor = UIColor.whiteColor()
view.addSubview(passwordTxtField)
loginButton.setTitle("Login", forState: .Normal)
loginButton.backgroundColor = UIColor.whiteColor()
loginButton.frame = CGRect(x: 20, y: 200, width: 200, height: 40)
view.addSubview(loginButton)
// 1
let viewModel = ViewModel(
withLogin: loginTxtField.rx_text.asObservable(),
password: passwordTxtField.rx_text.asObservable(),
didPressButton: loginButton.rx_tap.asObservable()
)
// 2
viewModel.authResponse
.subscribeNext { response in
print(response)
}
.addDisposableTo(disposeBag)
}
}
Run Code Online (Sandbox Code Playgroud)
这是两个有趣的部分:
// 1:我们在初始化时将三个Observable注入ViewModel.
// 2:然后我们订阅ViewModel的输出以Auth在登录完成后接收模型.
ViewModel:
import RxSwift
struct Auth {
let token: String
}
struct AuthResponse {
let token: String
}
class ViewModel {
// Output
let authResponse: Observable<Auth>
init(withLogin login: Observable<String>, password: Observable<String>, didPressButton: Observable<Void>) {
let mockAuthService = MockAuthService()
// 1
let userInputs = Observable.combineLatest(login, password) { (login, password) -> (String, String) in
return (login, password)
}
// 2
authResponse = didPressButton
.withLatestFrom(userInputs)
.flatMap { (login, password) in
return mockAuthService.getAuthToken(withLogin: login, mergedHash: password)
}
.map { authResponse in
return Auth(token: authResponse.token)
}
}
}
class MockAuthService {
func getAuthToken(withLogin login: String, mergedHash: String) -> Observable<AuthResponse> {
let dummyAuthResponse = AuthResponse(token: "dummyToken->login:\(login), password:\(mergedHash)")
return Observable.just(dummyAuthResponse)
}
}
Run Code Online (Sandbox Code Playgroud)
ViewModel在其init方法中获取3个Observable并将它们连接到它的输出:
// 1:将登录文本字段的最新值和密码文本字段的最新值组合到一个Observable中.
// 2:当用户按下按钮时,使用登录文本字段的最新值和密码文本字段的最新值,并将其传递给auth服务flatMap.当auth客户端返回a时AuthResponse,将其映射到Auth模型.设置此"链"的结果作为authResponse输出ViewModel
第一种方法使用PublishSubject
class ViewController: UIViewController {
@IBOutlet weak var loginBtn: UIButton!
var vm: ViewModel?
let disposebag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
bindUi()
}
func bindUi() {
(loginBtn.rx.tap).bind(to: vm!.loginSbj).addDisposableTo(disposebag)
}
}
class ViewModel {
let loginSbj = PublishSubject<Void>()
init() {
loginSbj.do(onNext: { _ in
// do something
})
}
}
Run Code Online (Sandbox Code Playgroud)
第二种方法使用Action
class ViewController: UIViewController {
@IBOutlet weak var loginBtn: UIButton!
var vm: ViewModel?
override func viewDidLoad() {
super.viewDidLoad()
bindUi()
}
func bindUi() {
loginBtn.rx.action = vm!.loginAction
}
}
class ViewModel {
let loginAction: CococaAction<Void, Void> = CocoaAction {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11468 次 |
| 最近记录: |