根據(jù)自己對RxSwift的理解寫了一個登陸以及驗證碼倒計時
Observer
一個可以被觀察的對象被觀察者監(jiān)聽
Observerable
觀察者 產(chǎn)生信號推送給訂閱者
/// A type-erased `ObservableType`.
///
/// It represents a push style sequence.
public class Observable<Element> : ObservableType {
登陸業(yè)務(wù)的整體處理邏輯為
整個業(yè)務(wù)處理流程為 創(chuàng)建 (賬號密碼輸入框文字改變)的觀察者 ---》 發(fā)送響應(yīng)信號 ---》 篩選并合并響應(yīng)信號 ===》 訂閱收到相應(yīng)信號并處理
首先創(chuàng)建賬號文字改變和密碼文字改變的觀察者 然后通過這個序列得到一個新的賬號密碼是否符合規(guī)范的序列輸入框改變后通知accontobseque響應(yīng) 最后將兩個序列信號合并條件符合后再通知loginobserver(Observer)進行響應(yīng)的ui處理
///
let inputaccontObserVerable = accontTextField.rx.text
let inputpasswordObserVerable = passwordTextField.rx.text
/**
Returns an observable sequence that **shares a single subscription to the underlying sequence**, and immediately upon subscription replays elements in buffer.
This operator is equivalent to:
* `.whileConnected`
```
// Each connection will have it's own subject instance to store replay events.
// Connections will be isolated from each another.
source.multicast(makeSubject: { Replay.create(bufferSize: replay) }).refCount()
```
* `.forever`
```
// One subject will store replay events for all connections to source.
// Connections won't be isolated from each another.
source.multicast(Replay.create(bufferSize: replay)).refCount()
```
It uses optimized versions of the operators for most common operations.
- parameter replay: Maximum element count of the replay buffer.
- parameter scope: Lifetime scope of sharing subject. For more information see `SubjectLifetimeScope` enum.
- seealso: [shareReplay operator on reactivex.io](http://reactivex.io/documentation/operators/replay.html)
- returns: An observable sequence that contains the elements of a sequence produced by multicasting the source sequence.
*/
// shareReplay 會返回一個新的事件序列藤肢,它監(jiān)聽底層序列的事件饮潦,并且通知自己的訂閱者們。
// 解決有多個訂閱者的情況下,map會被執(zhí)行多次的問題轧粟。
// 返回一個可觀察序列遭庶,該序列**共享對基礎(chǔ)序列**的單個訂閱蟆技,并在訂閱后立即在緩沖區(qū)中重播元素加缘。
//參數(shù)replay:重放緩沖區(qū)的最大元素計數(shù)。
// public func share(replay: Int = default, scope: RxSwift.SubjectLifetimeScope = default) -> RxSwift.Observable<Self.E>
let accontobseque = inputaccontObserVerable.share(replay: 1).map {
return $0!.count == 11
}
/// 返回一個可觀察的序列 比如 輸入的信號為 1霹娄,12能犯,123 那么將這個信號轉(zhuǎn)換為 false,false犬耻,false踩晶,具體可以根據(jù)業(yè)務(wù)需求來
let passwordseque = inputpasswordObserVerable.share(replay: 1).map {
return $0!.count == 6
}
//返回username和password組合后的流
let _ = Observable.combineLatest(accont.asObservable(), password.asObservable()) {
return ($0, $1)
}.bind(to: loginobserver)
extension LoginViewController {
/// 被觀察者 loginobserver
private var loginobserver: AnyObserver<Bool> {
return AnyObserver.init(eventHandler: { [weak self] (event) in
if let canlogin = event.element {
self?.loginBtn.backgroundColor = canlogin ? UIColor.red:UIColor.gray
}
}).asObserver()
}
ui邏輯整理好后處理業(yè)務(wù)邏輯新建一個LoginViewmodel
初始化方法為
convenience init(vc: LoginViewController) {
self.init()
self.ctr = vc
setUpBindSignal()
}
實現(xiàn)業(yè)務(wù)與界面的雙向綁定
var accont: Driver<String?>!
var password: Driver<String?>!
var msmcode: Driver<String>!
let msmhaviorsubject = BehaviorSubject<String>.init(value: "")
private func setUpBindSignal() {
accont = (ctr.accontTextField.rx.text).asDriver()
password = (ctr.passwordTextField.rx.text).asDriver()
let _ = msmhaviorsubject.asDriver(onErrorJustReturn: "").drive(ctr.msmlab.rx.text)
}
當點擊登錄方法后合并賬號和密碼信息通過flatmaplatest返回一個觀察者對象等到完成后通知綁定的業(yè)務(wù)邏輯進行登錄處理
//返回username和password組合后的流
let _ = Observable.combineLatest(accont.asObservable(), password.asObservable()) {
return ($0, $1)
}.flatMapLatest { (arg0) -> Observable<Loginmodel> in
let (user, pass) = arg0
debugPrint("用戶名:\(user!) 密碼:\(pass!)")
return self.client.login(accont: user!, password: pass!)
}.bind(to: ctr.finishbserver)
extension LoginViewController {
var finishbserver: AnyObserver<Loginmodel> {
return AnyObserver.init(eventHandler: { [weak self] (event) in
if let loginmodel = event.element {
self?.loginstatusLab.text = loginmodel.username
}
}).asObserver()
}
}
網(wǎng)絡(luò)請求層處理到此一個完整的登錄和結(jié)果展示就成功了還有一個短信驗證碼倒計時實現(xiàn)了與界面的綁定。
class NetClient: NSObject {
func login(accont: String,password: String) -> Observable<Loginmodel> {
return Observable<Loginmodel>.create({ (event) -> Disposable in
sleep(2)
let loginmodel = Loginmodel()
loginmodel.status = "登錄成功"
loginmodel.username = "紅鯉魚與綠鯉魚與驢"
/// 直接向訂閱者發(fā)送信號
event.on(Event.next(loginmodel))
event.on(Event.completed)
//event.onNext(<#T##element: Loginmodel##Loginmodel#>)
//event.onError(<#T##error: Error##Error#>)
//event.onCompleted()
/// 訂閱next信號 和 err信號 還有完成信號 并進行不同的處理
///訂閱方法為 subsrcir(onnext...,onerror:....,oncomplete:...,ondisponse:.... )
///subscribe(onNext: <#T##((Loginmodel) -> Void)?##((Loginmodel) -> Void)?##(Loginmodel) -> Void#>, onError: <#T##((Error) -> Void)?##((Error) -> Void)?##(Error) -> Void#>, onCompleted: <#T##(() -> Void)?##(() -> Void)?##() -> Void#>, onDisposed: <#T##(() -> Void)?##(() -> Void)?##() -> Void#>)
return Disposables.create {
}
})
}
}
map
這個方法跟數(shù)組自帶的api一樣map遍歷一個數(shù)組通過transform處理這個數(shù)組并得到一個期望返回值的數(shù)組例如
var arr = [1,2,3,4]
let newer = arr.map<Bool>.map {
/// 處理
}
那么newarr就是一個bool類型的數(shù)組
同理 遍歷這個
public func map<R>(_ transform: @escaping (Self.E) throws -> R) -> RxSwift.Observable<R>
flatmap
flatMap, flatMapLatest 讓觀察者觀察的東西變成動態(tài)的了. 后者是只觀察最后一個值.
let _ = Observable.combineLatest(accont.asObservable(), password.asObservable()) {
return ($0, $1)
}.flatMapLatest { (arg0) -> Observable<Loginmodel> in
let (user, pass) = arg0
debugPrint("用戶名:\(user!) 密碼:\(pass!)")
return self.client.login(accont: user!, password: pass!)
}.bind(to: ctr.finishbserver)
上述代碼段將用戶名和密碼最后一個值進行和處理生成了一組新的observerable
Driver
driver與observerable在功能上它類似被觀察者(Observable)枕磁,而它本身也可以與轉(zhuǎn)換成被觀察者(Observable: asDriver, Driver: asObservable)渡蜻,他不可以發(fā)送err事件 所以一旦發(fā)生錯誤會有容錯處理(onErrorJustReturn: "")
Driver序列不允許發(fā)出error,
Driver序列的監(jiān)聽只會在主線程中透典。
所以Driver是專為UI綁定量身打造的東西。
以下情況你可以使用Driver替換BindTo:
不能發(fā)出error;
在主線程中監(jiān)聽;
共享事件流;
BehaviorSubject
/// Represents a value that changes over time.
///
/// Observers can subscribe to the subject to receive the last (or initial) value and all subsequent notifications.
他既可以當做觀察者也可以當做被觀察者
具體可以參考Rxswift的subject