前言
- 本文系RxSwift基礎(chǔ)用法學(xué)習(xí),適用于已經(jīng)掌握swift基礎(chǔ)的programmer蹋订。
- RxSwift常作為MVVM的開發(fā)工具侦高,如果對MVVM不熟悉的工育,建議先學(xué)習(xí)!當(dāng)然兩者也可以一起學(xué)習(xí)肝箱!推薦干貨集中營-ReactiveCocoa+RXSwift+MVVM.
- 官網(wǎng)學(xué)習(xí)地址
- 本文系本人學(xué)習(xí)筆記五督,如有失誤匀奏,歡迎各位大神指正矢腻!
- 文章結(jié)尾有demo门驾,demo中的登錄模塊使用的是MVVM模式,歡迎交流!
步入正題
0.為什么學(xué)習(xí)RxSwift
編程過程中有很多代碼是關(guān)于事件響應(yīng)的多柑,當(dāng)用戶操作控制器時猎唁,我們需要通過Action來響應(yīng)事件,通過通知來監(jiān)測鍵盤高度顷蟆,通過閉包來執(zhí)行網(wǎng)絡(luò)請求的響應(yīng),通過KVO來監(jiān)測值的改變腐魂,如果有一樣工具可以實現(xiàn)以上所有功能帐偎,那么RxSwift就是了!
RxSwift是ReactiveX在swift上的實現(xiàn)蛔屹,在Java削樊,C#,.net等語言和平臺上都可以找到他的身影兔毒,所以就出現(xiàn)了這樣一件有意思的事情漫贞,當(dāng)你遇到問題時,或許在其他語言平臺上可以找到你想要的答案育叁。
舉個??:在編碼時我們需要很多耦合事件迅脐,把事件之間的耦合比作網(wǎng)絡(luò)連接,以前我們需要冗長的網(wǎng)線來連接豪嗽,有了RxSwift谴蔑,你就可以使用WiFi了!
1.創(chuàng)建和訂閱可觀測序列
RxSwift中的核心類就是Observable龟梦,它就像一個路由器一樣把事件轉(zhuǎn)換成信號發(fā)給訂閱者隐锭!其實現(xiàn)思路類似于通知,但通知屬于其子集计贰。
- empty
/// 創(chuàng)建一個銷毀包
let disposeBag = DisposeBag()
/// 創(chuàng)建一個空的可觀測序列
let emptyObservable = Observable<Any>.empty()
/// 訂閱空的觀察者
emptyObservable.subscribe { event in
print("empty")
}.disposed(by: disposeBag)
先看disposeBag它的作用是用來銷毀無用的可觀測序列钦睡,emptyObserable是一個空的可觀測序列,當(dāng)某個事件發(fā)生時躁倒,但訂閱者不需要知道發(fā)生了什么時荞怒,我們就可以使用發(fā)送一個空信號來告知訂閱者洒琢。之后就是訂閱了,訂閱之后就可以拿到觀察序列發(fā)出的信號挣输,但這里的觀測序列所攜帶的事件為空纬凤,所以event也為空,下面來看帶信號的觀測序列撩嚼。
- just
/// 創(chuàng)建單個元素/事件的可觀測序列
Observable.just("??")
.subscribe { event in
print(event)
}
.disposed(by: disposeBag)
/// 打印結(jié)果:??
這里創(chuàng)建的是只包含單個元素的可觀測序列停士,這里的元素可以是我們常用的數(shù)據(jù)類型,也可以是對象等完丽。在訂閱之后即可拿到事件或數(shù)據(jù)恋技!
- of
/// 創(chuàng)建包含多個元素的可觀測序列
Observable.of("??", "??", "??", "??")
.subscribe(onNext: { element in
print(element)
})
.disposed(by: disposeBag)
/// 打印結(jié)果:
??
??
??
??
當(dāng)一個事件存在多個參數(shù)時,我們可以使用此方法
- from
/// 創(chuàng)建包含一個集合的可觀測序列逻族,集合可以是Array蜻底,Dictionary,Set
Observable.from(["??", "??", "??", "??"])
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
/// 打印結(jié)果:
??
??
??
??
上面幾個方法只是簡單的實現(xiàn)了信號/事件流的發(fā)送與訂閱聘鳞,但是在實際使用使用過程中往往需要自己來定制可觀測序列薄辅。
- create/custom
///通過傳入的元素來創(chuàng)建可觀測序列
let myJust = { (element: String) -> Observable<String> in
return Observable.create { observer in
observer.on(.next(element))
observer.on(.completed)
return Disposables.create()
}
}
/// 創(chuàng)建一個包含 ?? 的可觀測序列
let newObserver = myJust("??")
/// 訂閱觀測序列
newObserver.subscribe { print($0) }.disposed(by: disposeBag)
如果理解了上面的例子以后,這個也定不成問題了抠璃!
然后還有幾個方法
- never
/// 創(chuàng)建一個永遠(yuǎn)不會執(zhí)行的序列站楚,不知道有什么用!
Observable<String>.never().subscribe { _ in
print("This will never be printed")
}
- error
/// 創(chuàng)建一個序列搏嗡,沒有事件窿春,而是error,且立即停止執(zhí)行
Observable<Int>.error(TestError.test)
.subscribe { print($0) }
.disposed(by: disposeBag)
- range
/// 創(chuàng)建一個序列采盒,發(fā)送范圍內(nèi)integer類型數(shù)據(jù)
Observable.range(start: 1, count: 10)
.subscribe { print($0) }
.disposed(by: disposeBag)
- repeatElement
/// 創(chuàng)建一個序列旧乞,發(fā)送已給定的元素,take的參數(shù)表示repead的次數(shù)
Observable.repeatElement("??")
.take(3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
- generate
/// 創(chuàng)建一個序列磅氨,當(dāng)給出的條件為真時尺栖,會一直發(fā)送信號
Observable.generate(
initialState: 0,
condition: { $0 < 3 },
iterate: { $0 + 1 }
)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
- deferred
/// 創(chuàng)建一個序列,為每一個訂閱者都提供一個新的序列烦租,為了保證訂閱者拿到的是最新的數(shù)據(jù)時决瞳,可以使用此方法
var count = 1
let deferredSequence = Observable<String>.deferred {
print("Creating \(count)")
count += 1
return Observable.create { observer in
print("Emitting...")
observer.onNext("??")
observer.onNext("??")
observer.onNext("??")
return Disposables.create()
}
}
deferredSequence
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
deferredSequence
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
** 小結(jié):Observable是一個比較抽象的類,RxSwift中提供了多樣的方法來最大程度的方便使用左权,大家也可根據(jù)自己的實際情況來靈活應(yīng)用皮胡!另外在實際情況中我們往往是希望全面掌控事件的發(fā)送與接收,下面的Subjects即可實現(xiàn)我們的需求赏迟。**
2.使用Subjects來工作
下面提到的subjects都是Observable的子類屡贺,相對于Observable,subject使用起來更加靈活,它既可以作為訂閱者甩栈,也可以作為觀測序列泻仙,因而能夠多次訂閱以及發(fā)送新的事件。
- 先來個擴展方法量没,方便下文使用玉转,這個方法實現(xiàn)了對subject的訂閱,同時打印出發(fā)送的事件殴蹄,參數(shù)id是一個標(biāo)識符
/**
Add observer with `id` and print each emitted event.
- parameter id: an identifier for the subscription.
*/
func addObserver(_ id: String) -> Disposable {
return subscribe { print("Subscription:", id, "Event:", $0) }
}
-
PublishSubject
向所有訂閱者廣播最新事件
/// method 1
/// 創(chuàng)建銷毀包
let disposeBag = DisposeBag()
/// 創(chuàng)建subject
let subject = PublishSubject<String>()
/// 實現(xiàn)訂閱,下面訂閱方法二選一究抓,訂閱需要在發(fā)送信號之前實現(xiàn),對應(yīng)MVVM中一個思路:在拿到數(shù)據(jù)之前就要實現(xiàn)拿到數(shù)據(jù)之后的操作
subject.addObserver("1").disposed(by: disposeBag) // 上文中封裝的訂閱
subject.subscribe { print($0) }.disposed(by: disposeBag) // 原生訂閱方法
/// 發(fā)送事件??
subject.onNext("??")
/// 發(fā)送事件??
subject.onNext("??")
/// 打印結(jié)果
--- PublishSubject example ---
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
-
ReplaySubject
向訂閱者發(fā)送指定數(shù)量的事件袭灯,意思就是從最近發(fā)送的事件開始以0算起刺下,逆序發(fā)送之前發(fā)送過的事件
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 2)
/// 訂閱者1
subject.addObserver("1").disposed(by: disposeBag)
subject.onNext("lol")
subject.onNext("??")
subject.onNext("??")
/// 訂閱者2
subject.addObserver("2").disposed(by: disposeBag)
subject.onNext("???")
subject.onNext("???")
/// 打印結(jié)果
--- ReplaySubject example ---
Subscription: 1 Event: next(lol)
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
-
BehaviorSubject
向所有訂閱者廣播事件,先最新的訂閱者發(fā)送最新事件稽荧,使用方法與PublishSubject很相似
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "??")
/// 第一個訂閱者
subject.addObserver("1").disposed(by: disposeBag) subject.onNext("??")
subject.onNext("??")
/// 第二個訂閱者
subject.addObserver("2").disposed(by: disposeBag)
subject.onNext("???")
subject.onNext("???")
/// 第三個訂閱者
subject.addObserver("3").disposed(by: disposeBag)
subject.onNext("??")
subject.onNext("??")
/// 打印結(jié)果
--- BehaviorSubject example ---
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 3 Event: next(???)
Subscription: 1 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 3 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 3 Event: next(??)
-
Variable
Variable是對BehaviorSubject的封裝橘茉,所以它可以向訂閱者們發(fā)送最新的值,而且可以維持值的狀態(tài)姨丈,它不會發(fā)送error畅卓,但是發(fā)生錯誤是會發(fā)送comepleted事件并結(jié)束。
let disposeBag = DisposeBag()
let variable = Variable("??")
/// 訂閱者1
variable.asObservable().addObserver("1").disposed(by: disposeBag)
variable.value = "??"
variable.value = "??"
/// 訂閱者2
variable.asObservable().addObserver("2").disposed(by: disposeBag)
variable.value = "???"
variable.value = "???"
/// 打印結(jié)果
--- Variable example ---
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 1 Event: next(??)
Subscription: 2 Event: next(??)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 1 Event: next(???)
Subscription: 2 Event: next(???)
Subscription: 1 Event: completed
Subscription: 2 Event: completed
** 掌握了以上的方法蟋恬,基本就可以愉快的發(fā)送翁潘,訂閱事件了,上手MVVM也不會有什么大問題筋现!**
3. 關(guān)聯(lián)文章
Swift進(jìn)階之RxSwift(二)
Swift進(jìn)階之RxSwift(三)
Swift進(jìn)階之RxSwift(四)
Demo地址,個人水平有限箱歧,如有問題矾飞,歡迎指出!
** 如果覺的本文有用的話呀邢,動動小手洒沦,點個贊!有問題可以在下方留言价淌!**