前言
- 本文系RxSwift基礎(chǔ)用法學習,適用于已經(jīng)掌握swift基礎(chǔ)的programmer。
- RxSwift常作為MVVM的開發(fā)工具,如果對MVVM不熟悉的,建議先學習!當然兩者也可以一起學習!推薦干貨集中營-ReactiveCocoa+RXSwift+MVVM.
- 官網(wǎng)學習地址
- 本文系本人學習筆記,如有失誤,歡迎各位大神指正!
- 文章結(jié)尾有demo,demo中的登錄模塊使用的是MVVM模式,歡迎交流!
步入正題
0.為什么學習RxSwift
編程過程中有很多代碼是關(guān)于事件響應(yī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)了這樣一件有意思的事情,當你遇到問題時,或許在其他語言平臺上可以找到你想要的答案。
舉個??:在編碼時我們需要很多耦合事件,把事件之間的耦合比作網(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是一個空的可觀測序列,當某個事件發(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é)果:
??
??
??
??
當一個事件存在多個參數(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)建一個永遠不會執(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)建一個序列,當給出的條件為真時,會一直發(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是一個標識符
/**
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進階之RxSwift(二)
Swift進階之RxSwift(三)
Swift進階之RxSwift(四)
Demo地址,個人水平有限,如有問題,歡迎指出!
** 如果覺的本文有用的話,動動小手,點個贊!有問題可以在下方留言!**