前言
RxSwift的目的是讓數(shù)據(jù)/事件流和異步任務(wù)能夠更方便的序列化處理往毡,能夠使用Swift進(jìn)行響應(yīng)式編程拖吼。
本文的目的:
- 介紹RxSwift的核心思想
- 講解RxSwift的基礎(chǔ)使用
- 介紹RxSwift的優(yōu)點(diǎn)
RxSwif
t的核心是想是Observable<Element> sequence
惊来,Observable
表示可監(jiān)聽或者可觀察,也就是說(shuō)RxSwift的
核心思想是可監(jiān)聽的序列砾嫉。并且杉编,Observable sequence
可以接受異步信號(hào),也就是說(shuō)赌厅,信號(hào)是可以異步給監(jiān)聽者的穷绵。
-
Observable(ObservableType)
和SequenceType
類似 -
ObservableType.subscribe
和SequenceType.generate
類似 - 由于
RxSwift
支持異步獲得信號(hào),所以用ObservableType.subscribe
特愿,這和indexGenerator.next()
類似仲墨。
本文把RxSwift
中的序列的每一個(gè)Element
成為信號(hào),因?yàn)楫惒降?code>Element是與時(shí)間相關(guān)的,稱作信號(hào)更好理解一點(diǎn)揍障。
RxSwift
中目养,ObservableType.subscribe
的回調(diào)(新的信號(hào)到來(lái))一共有三種
enum Event<Element> {
case Next(Element) // 新的信號(hào)到來(lái)
case Error(ErrorType) // 信號(hào)發(fā)生錯(cuò)誤,序列不會(huì)再產(chǎn)生信號(hào)
case Completed // 序列發(fā)送信號(hào)完成毒嫡,不會(huì)再產(chǎn)生新的信號(hào)
}
protocol ObserverType {
func on(event: Event<Element>) //監(jiān)聽所有的信號(hào)
}
取消監(jiān)聽
Observable
分為兩種
- 在有限的時(shí)間內(nèi)會(huì)自動(dòng)結(jié)束
(Completed/Error)
,比如一個(gè)網(wǎng)絡(luò)請(qǐng)求當(dāng)作一個(gè)序列癌蚁,當(dāng)網(wǎng)絡(luò)請(qǐng)求完成的時(shí)候,Observable
自動(dòng)結(jié)束兜畸,資源會(huì)被釋放
2.信號(hào)不會(huì)自己結(jié)束努释,最簡(jiǎn)單的比如一個(gè)Timer
,每隔一段時(shí)間發(fā)送一個(gè)新的信號(hào)過來(lái)咬摇,這時(shí)候需要手動(dòng)取消監(jiān)聽伐蒂,來(lái)釋放相應(yīng)的資源,又比如一個(gè)label.rac_text
是一個(gè)Obserable
,通常需要這樣調(diào)用addDisposableTo(disposeBag)
來(lái)讓其在deinit
肛鹏,也就是所有者要釋放的時(shí)候逸邦,自動(dòng)取消監(jiān)聽。
class Observable<Element> {
func subscribe(observer: Observer<Element>) -> Disposable //調(diào)用Disposable的方法來(lái)取消
}
當(dāng)然在扰,除了手動(dòng)釋放缕减,RxSwift
提供了一些操作符,比如takeUntil
來(lái)根據(jù)條件取消
sequence
.takeUntil(self.rx_deallocated) //當(dāng)對(duì)象要釋放的時(shí)候健田,取消監(jiān)聽
.subscribe {
print($0)
}
信號(hào)處理的順序
Observable
有個(gè)隱式的約定烛卧,那就是在一個(gè)信號(hào)處理完成之前,不會(huì)發(fā)送下一個(gè)信號(hào)妓局,不管發(fā)送信號(hào)的線程是并發(fā)的or串行的总放。
例如
someObservable
.subscribe { (e: Event<Element>) in
print("Event processing started")
// processing
print("Event processing ended")
}
只會(huì)出現(xiàn)
[圖片上傳中...(正確結(jié)果.png-5f2e8d-1521776416167-0)]
不會(huì)出現(xiàn)的結(jié)果
第一個(gè)例子
我們監(jiān)聽textfield
的文字變化,然后好爬,Log
出text
局雄,當(dāng)button
點(diǎn)擊的時(shí)候,取消這次監(jiān)聽
class ObservableAndCancelController : UIViewController{
var subscription:Disposable?
@IBOutlet weak var textfield: UITextField!
@IBAction func cancelObserve(sender: AnyObject) {
subscription?.dispose()
}
override func viewDidLoad() {
super.viewDidLoad()
subscription = textfield.rx_text.subscribeNext { (text) in
print(text)
}
}
}
RxSwift
用extensiton
的方式存炮,為UITextfield
,UIlabel
等控件添加了很多可監(jiān)聽的屬性炬搭,這里的textfield.rx_text
就是一個(gè)
操作符(Operators)
在上文的第一個(gè)例子里面蜈漓,你看到了監(jiān)聽信號(hào),并且log
出值宫盔。事實(shí)上融虽,這樣直接處理信號(hào)的時(shí)候是很少的,很多時(shí)候灼芭,我們需要對(duì)信號(hào)進(jìn)行映射有额,過濾,這時(shí)候我們就要用到操作符了彼绷。在這個(gè)文檔里巍佑,你可以找到所有的操作符。
關(guān)于操作符效果寄悯,你可以參見http://rxmarbles.com/的可視化效果萤衰,這會(huì)給你一個(gè)更好的理解
例子二 map,filter,combineLatest
- map 對(duì)信號(hào)(Element)進(jìn)行映射處理。比如輸入是String猜旬,影射到Bool
- filter 對(duì)信號(hào)(Element)進(jìn)行過濾處理脆栋。返回信號(hào),和輸入的信號(hào)是同一種類型
- combineLatest 對(duì)兩種信號(hào)的值進(jìn)行結(jié)合昔馋〕锿拢可以返回不同種類的信號(hào)糖耸。
例如
let firstObserverable = firstTextfield.rx_text.map({"first" + $0})
let secondObserverable = secondTextfield.rx_text.filter({$0.characters.count > 3})
_ = Observable.combineLatest(firstObserverable, secondObserverable, resultSelector:{ ($0 + $1,$0.characters.count + $1.characters.count)}).subscribeNext { (element) in
print("combineLatest:\(element)")
}
對(duì)于秘遏,每一個(gè)fistTextfield
的信號(hào),在字符串開始處增加”first”
嘉竟;
對(duì)secondTextfield
的信號(hào)進(jìn)行過濾邦危,當(dāng)長(zhǎng)度大于3
的時(shí)候,才會(huì)繼續(xù)傳遞;
對(duì)兩個(gè)信號(hào)進(jìn)行結(jié)合舍扰,取truple
類型倦蚪,然后打印出來(lái)。
所以边苹,當(dāng)我在fistTextfield中陵且,輸入1234,然后secondTextfield中依次輸入abcdefg的時(shí)候
例子三 創(chuàng)建一個(gè)Observable
Observerable
可以用來(lái)處理任務(wù)个束,并且異步返回Event
信號(hào)(Next,Error,Completion)
比如慕购,這樣一個(gè)方法
//Observable就是處理輸入,并且把description發(fā)送出去
func createObserveable(object:AnyObject?)->Observable<String?>{
return Observable.create({ observer in
observer.onNext(object?.description)
observer.onCompleted()
return NopDisposable.instance
})
}
這樣調(diào)用
_ = createObserveable(test).subscribe({ (event) in
switch event{
case .Next(let value):
print(value)
case .Completed:
print("Completed")
case .Error(let error):
print(error)
}
})
可以看到茬底,創(chuàng)建一個(gè)Observable
相當(dāng)容易沪悲,調(diào)用Observable.create
,在必要的時(shí)候發(fā)送onNext
,onError
,onCompleted
信號(hào)阱表。然后返回一個(gè)Disposable
用來(lái)取消信號(hào)
throttle/retry/distinctUntilChanged/flatMapLatest
- throttle 忽略上一個(gè)信號(hào)的一段時(shí)間的變化,也就是說(shuō)一段時(shí)間沒有新的信號(hào)輸入殿如,才會(huì)向下發(fā)送
- distinctUntilChanged 直到信號(hào)改變了再發(fā)送
- retry 如果失敗贡珊,重新嘗試的次數(shù)
- flatMapLatest 僅僅執(zhí)行最新的信號(hào),當(dāng)有新的信號(hào)來(lái)的時(shí)候涉馁,取消上一次未執(zhí)行完的整個(gè)序列
最直接的例子就是搜索门岔,通常我們想要
1.用戶用一段時(shí)間沒有輸入的時(shí)候,在進(jìn)進(jìn)行網(wǎng)絡(luò)請(qǐng)求烤送,不然網(wǎng)絡(luò)請(qǐng)求太頻繁固歪,對(duì)客戶端和服務(wù)器都是負(fù)擔(dān)
2.當(dāng)新的請(qǐng)求來(lái)的時(shí)候,如果上一個(gè)未完成胯努,則取消上一個(gè)
3.如果網(wǎng)絡(luò)失敗牢裳,能重新請(qǐng)求幾次就更好了
這時(shí)候,用RxSwift你得代碼會(huì)變的非常簡(jiǎn)單
let searchResults = searchBar.rx_text
.throttle(0.3, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { query -> Observable<[Repository]> in
if query.isEmpty {
return Observable.just([])
}
return doSearchAPI(query).retry(3)
.catchErrorJustReturn([])
}
.observeOn(MainScheduler.instance)
這里簡(jiǎn)單講解下作用
-
throttle(0.3, scheduler: MainScheduler.instance)
保證用戶沒有輸入0.3
秒后再進(jìn)行下一步 -
distinctUntilChanged()
假如0.3
秒之前輸入是ab
叶沛,0.3
秒后還是ab
,則不會(huì)進(jìn)行下一步蒲讯,只有改變了才會(huì)進(jìn)行下一步 -
flatMapLatest
保證只搜索最新的,如果之前的沒有完成灰署,會(huì)被自動(dòng)取消 -
doSearchAPI(query).retry(3)
保證判帮,如果發(fā)生錯(cuò)誤,自動(dòng)重試3
次溉箕。
Schedulers
Schedulers 抽象化了線程晦墙,線程池,GCD中操作隊(duì)列肴茄,Runloop等概念晌畅。可以理解為寡痰,Schedulers就是一個(gè)執(zhí)行任務(wù)的線程抗楔。
有一點(diǎn)要注意:默認(rèn)一個(gè)Observerable
在其創(chuàng)建的線程上執(zhí)行
與Schedulers
相關(guān)的操作符有兩個(gè)
-
observeOn(scheduler)
在一個(gè)scheduler
上執(zhí)行任務(wù),使用場(chǎng)景較多 -
subscribeOn(scheduler)
在一個(gè)scheduler
進(jìn)行監(jiān)聽
比如:
sequence1
.observeOn(backgroundScheduler)
.map { n in
print("This is performed on the background scheduler")
}
.observeOn(MainScheduler.instance)
.map { n in
print("This is performed on the main scheduler")
}.subscribeOn(backgroundScheduler)
.subscribeNext{ n in
print("This is performed on the background scheduler")
}
__ 默認(rèn)一個(gè)subscribeNext或者subscribe在其調(diào)用的線程上執(zhí)行__
Serial/Concurrent Schedulers 串行或并行
和GCD
的隊(duì)列很相似拦坠,并行Schedulers
的任務(wù)可以并發(fā)之行连躏,串行Schedulers
只能依次執(zhí)行。不過RxSwift有內(nèi)部機(jī)制贞滨,保證上文提到的信號(hào)處理的順序
RxSwift內(nèi)置的Scheduler
通常入热,使用內(nèi)置的Scheduler
足矣。
-
CurrentThreadScheduler
(串行) 當(dāng)前線程Scheduler
晓铆,默認(rèn)使用的 -
MainScheduler
(串行) 主線程 -
SerialDispatchQueueScheduler
封裝了GCD
的串行隊(duì)列 -
ConcurrentDispatchQueueScheduler
封裝了GCD
的并行隊(duì)列勺良,這個(gè)在有任務(wù)要在后臺(tái)執(zhí)行的時(shí)候很有用 -
OperationQueueScheduler
封裝了NSOperationQueue
例子四,在后臺(tái)Scheduler之行任務(wù)尤蒿,然后在主線程上更新UI
Variable
Variable表示一個(gè)可監(jiān)聽的數(shù)據(jù)結(jié)構(gòu)郑气。使用Variable,你可以監(jiān)聽數(shù)據(jù)的變化腰池,也可以把其他值綁定到它身上尾组。
當(dāng)Variable被釋放的時(shí)候忙芒,它會(huì)向監(jiān)聽者發(fā)送onCompleted
例子五,Variable
進(jìn)行監(jiān)聽
class VariableController: UIViewController {
@IBOutlet weak var label: UILabel!
var timer:NSTimer?
var count = Variable(0)
override func viewDidLoad() {
super.viewDidLoad()
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector:#selector(VariableController.updateValue) , userInfo: nil, repeats: true)
_ = count.asObservable().subscribeNext { (num) in
self.label?.text = "VariableValue:\(num)"
}
}
func updateValue(){
count.value = count.value + 1
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
timer?.invalidate()
}
}
數(shù)據(jù)綁定
數(shù)據(jù)綁定是開發(fā)的時(shí)候很常見的讳侨,比如根據(jù)文本的輸入動(dòng)態(tài)調(diào)整textfield
的背景色呵萨,動(dòng)態(tài)調(diào)整按鈕的enable
。亦或者根據(jù)textfield
的輸入變化跨跨,動(dòng)態(tài)的去反饋到model
層潮峦。如果你聽過MVVM
,那你肯定知道勇婴,MVVM
的難點(diǎn)就是ViewModel
與View
的數(shù)據(jù)綁定問題忱嘹。
不過,使用RxSwift
耕渴,數(shù)據(jù)綁定變的十分容易拘悦,你甚至可以把數(shù)據(jù)綁定到tableview
和collectionView
上去。
例子六橱脸,bindTo
很簡(jiǎn)單础米,隨著Switch
的開關(guān),view
進(jìn)行顯示/隱藏
只需要一行代碼
_ = mySwitch.rx_value.bindTo(testView.rx_hidden)
例子七添诉,根據(jù)輸入屁桑,進(jìn)行View
狀態(tài)綁定
我們想要實(shí)現(xiàn)這樣的狀態(tài)
- 用戶名至少6位,小于6位栏赴,則背景色是灰色蘑斧,合法則透明
- 密碼至少位8位,小于8位艾帐,則背景色是灰色乌叶,合法則透明
- 當(dāng)用戶名和密碼都合法的時(shí)候,注冊(cè)按鈕enable柒爸,并且背景色變紅
信號(hào)的處理方式如下:
let nameObserable = nameTextfield.rx_text.shareReplay(1).map({$0.characters.count >= 6})
let pwdObserable = passwordTextfield.rx_text.shareReplay(1).map({$0.characters.count >= 8})
_ = nameObserable.subscribeNext({ (valid) in
self.nameTextfield.backgroundColor = valid ? UIColor.clearColor():UIColor.lightGrayColor()
}).addDisposableTo(disposeBag)
_ = pwdObserable.subscribeNext({ (valid) in
self.passwordTextfield.backgroundColor = valid ? UIColor.clearColor(): UIColor.lightGrayColor()
}).addDisposableTo(disposeBag)//addDisposableTo(disposeBag)是為了自動(dòng)釋放
_ = Observable.combineLatest(nameObserable, pwdObserable) {$0 && $1}.subscribeNext({valid in
if valid{
self.registerButton.enabled = true
self.registerButton.backgroundColor = UIColor.redColor()
}else{
self.registerButton.enabled = false
self.registerButton.backgroundColor = UIColor.darkGrayColor()
}
}).addDisposableTo(disposeBag)
_ = registerButton.rx_tap.shareReplay(1).subscribeNext {
print("Button tapped")
}
共享監(jiān)聽Sharing subscription-shareReplay
這個(gè)是很常用的,比如一個(gè)Obserable
用做網(wǎng)絡(luò)請(qǐng)求事扭,通常捎稚,當(dāng)你這樣調(diào)用的時(shí)候,會(huì)創(chuàng)建兩個(gè)序列求橄,也就是會(huì)進(jìn)行兩次網(wǎng)絡(luò)請(qǐng)求今野,這是不需要的
let network = networkWithText(text)
let subscription1 = network
.subscribeNext { n in
//創(chuàng)建第一個(gè)序列
}
let subscription2 = network
.subscribeNext { n in
//創(chuàng)建第二個(gè)序列
}
為了共享一個(gè)序列,你只需要這這樣調(diào)用
let network = networkWithText(text).shareReplay(1)
就只會(huì)進(jìn)行一次網(wǎng)絡(luò)請(qǐng)求罐农,兩個(gè)subscription
共享結(jié)果条霜,也就是shareReplay
的意思
自定義可綁定屬性
上文,textfield
和button
的狀態(tài)綁定是手動(dòng)的涵亏,這無(wú)疑是不方便的宰睡。RxSwift
為我們提供了一種方式蒲凶,來(lái)自定義可綁定屬性
創(chuàng)建兩個(gè)exetnsion
extension UITextField{
var ex_validState:AnyObserver<Bool>{
return UIBindingObserver(UIElement: self) { textfield, valid in
textfield.backgroundColor = valid ? UIColor.clearColor():UIColor.lightGrayColor()
}.asObserver()
}
}
extension UIButton{
var ex_validState:AnyObserver<Bool>{
return UIBindingObserver(UIElement: self) { button, valid in
button.enabled = valid
button.backgroundColor = valid ? UIColor.redColor() : UIColor.darkGrayColor()
}.asObserver()
}
}
然后,上文的代碼拆内,就可以簡(jiǎn)化成三行了旋圆,So easy
_ = nameObserable.bindTo(nameTextfield.ex_validState).addDisposableTo(disposeBag)
_ = pwdObserable.bindTo(passwordTextfield.ex_validState).addDisposableTo(disposeBag)
_ = Observable.combineLatest(nameObserable, pwdObserable) {$0 && $1}.bindTo(registerButton.ex_validState).addDisposableTo(disposeBag)
Driver
Driver
是RxSwift
精心制作的,專門提供給UI
層的一個(gè)接口麸恍。
利用Driver
你可以
- 利用
CoreData
的模型來(lái)驅(qū)動(dòng)UI
- 利用
UI
的狀態(tài)來(lái)綁定其他UI
的狀態(tài)
Driver能夠保證灵巧,在主線程上監(jiān)聽,因?yàn)閁IKit不是需要在主線程上操作
Tips:
RxSwift
中做數(shù)據(jù)綁定有三種
- 利用
BindTo
方法 - 利用
Driver
(強(qiáng)烈建議使用這個(gè)抹沪,) - 利用
KVO
來(lái)手動(dòng)綁定(很少用到)
回到Driver
上來(lái)刻肄,上文提到了,對(duì)于搜索融欧,我們可以這么做肄方,
let results = query.rx_text
.throttle(0.3, scheduler: MainScheduler.instance) //延遲0.3秒
.flatMapLatest { query in //永遠(yuǎn)只執(zhí)行最新的
searchWithText(query)
}
results
.map { "\($0.count)" }
.bindTo(resultCount.rx_text)//綁定label
.addDisposableTo(disposeBag)
results
.bindTo(resultsTableView.rx_itemsWithCellIdentifier("Cell")) { (_, result, cell) in //綁定tableview
cell.textLabel?.text = "\(result)"
}
.addDisposableTo(disposeBag)
那么,這有什么缺陷呢蹬癌?
假如searchWithText
失敗了权她,那么整個(gè)序列就斷掉了,后面的綁定不會(huì)有任何作用
假如searchWithText
是在后臺(tái)線程執(zhí)行的逝薪,那么后續(xù)綁定是在后臺(tái)線程上進(jìn)行的隅要,會(huì)崩潰
綁定了兩次,意味著會(huì)執(zhí)行兩次
于是董济,我們需要進(jìn)行額外的操作步清,來(lái)避免上述缺陷。
let results = query.rx_text
.throttle(0.3, scheduler: MainScheduler.instance)
.flatMapLatest { query in
fetchAutoCompleteItems(query)
.observeOn(MainScheduler.instance) // 保證在主線程(解決缺陷1)
.catchErrorJustReturn([]) // 發(fā)生錯(cuò)誤虏肾,返回空數(shù)組(解決缺陷2)
}
.shareReplay(1) // 共享監(jiān)聽廓啊,保證只執(zhí)行一次(解決缺陷3)
results
.map { "\($0.count)" }
.bindTo(resultCount.rx_text)
.addDisposableTo(disposeBag)
results
.bindTo(resultTableView.rx_itemsWithCellIdentifier("Cell")) { (_, result, cell) in
cell.textLabel?.text = "\(result)"
}
.addDisposableTo(disposeBag)
利用Driver
我們可以將上述過程簡(jiǎn)化
let results = query.rx_text.asDriver() // 轉(zhuǎn)換成Driver序列
.throttle(0.3, scheduler: MainScheduler.instance)
.flatMapLatest { query in
fetchAutoCompleteItems(query)
.asDriver(onErrorJustReturn: []) // 告訴Driver發(fā)生錯(cuò)誤怎么辦
}
results
.map { "\($0.count)" }
.drive(resultCount.rx_text) // 用Driver綁定,不需要切換到主線程
.addDisposableTo(disposeBag)
results
.drive(resultTableView.rx_itemsWithCellIdentifier("Cell")) { (_, result, cell) in
cell.textLabel?.text = "\(result)"
}
.addDisposableTo(disposeBag)
任何滿足以下三個(gè)條件的Observer
序列都可以轉(zhuǎn)換為Driver
- 不會(huì)因?yàn)殄e(cuò)誤就序列斷掉(比如封豪,有錯(cuò)誤谴轮,但是沒有調(diào)用
onError
來(lái)發(fā)送錯(cuò)誤)
2.在主線程傻姑娘監(jiān)聽
3.共享side effects
對(duì)于,使用者只需要調(diào)用asDriver(onErrorJustReturn: [])
就能保證上述三點(diǎn)都實(shí)現(xiàn)了
KVO
通常的KVO
吹埠,你需要在這個(gè)函數(shù)里來(lái)處理
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
而使用RxSwift
,KVO
變成了這樣
view.rx_observe(CGRect.self, "frame")
.subscribeNext { frame in
print("Got new frame \(frame)")
}
或者這樣
someSuspiciousViewController
.rx_observeWeakly(Bool.self, "behavingOk")
.subscribeNext { behavingOk in
print("Cats can purr? \(behavingOk)")
}
二者的區(qū)別是
在
rx_observe
可以使用地方都可以使用rx_observeWeakly
第步。rx_observeWeakly
的執(zhí)行效率要低一點(diǎn),因?yàn)橐幚韺?duì)象的dealloc
關(guān)系缘琅。除此之外粘都,rx_observeWeakly
還可以用在weak
屬性上。
在使用view.rx_observe的時(shí)候刷袍,有幾點(diǎn)要注意
由于KVO是建立在NSObject子類的基礎(chǔ)上的翩隧,你可以通過如下方法,來(lái)讓Structs支持KVO
Notification
使用RxSwift
呻纹,Notification
變的十分簡(jiǎn)潔
NSNotificationCenter.defaultCenter()
.rx_notification(UITextViewTextDidBeginEditingNotification, object: myTextView)
.map { /*do something with data*/ }
....
調(diào)試
使用Debug
操作符堆生,會(huì)log
所有的數(shù)據(jù)流
let subscription = myInterval(0.1)
.debug("my probe")
.map { e in
return "This is simply \(e)"
}
.subscribeNext { n in
print(n)
}
NSThread.sleepForTimeInterval(0.5)
subscription.dispose(
你可以用自定義操作符的方式专缠,來(lái) Log
extension ObservableType {
public func myDebug(identifier: String) -> Observable<Self.E> {
return Observable.create { observer in
print("subscribed \(identifier)")
let subscription = self.subscribe { e in
print("event \(identifier) \(e)")
switch e {
case .Next(let value):
observer.on(.Next(value))
case .Error(let error):
observer.on(.Error(error))
case .Completed:
observer.on(.Completed)
}
}
return AnonymousDisposable {
print("disposing \(identifier)")
subscription.dispose()
}
}
}
}
調(diào)試內(nèi)存泄漏問題
RxSwift
通過RxSwift.resourceCount
記錄資源分配情況,所以通常的調(diào)試方式如下
/* 在AppDelegate方法中添加Log
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
*/
_ = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.subscribeNext { _ in
print("Resource count \(RxSwift.resourceCount)")
}
然后
1.進(jìn)入相關(guān)界面顽频,進(jìn)行正常操作
2.退出界面
3.觀察RxSwift.resourceCount
4.在進(jìn)入同一個(gè)界面藤肢,退出
5.觀察RxSwift.resourceCount
使用心得
1.時(shí)刻牢記,使用RxSwift糯景,盡量把所有的任務(wù)(可以理解為方法)抽象成Obserable(序列)和Obserable創(chuàng)建者嘁圈,監(jiān)聽者
2.能用數(shù)據(jù)綁定的(bindTo和Driver)的就不要手動(dòng)綁定
3.一定要熟練RxSwift提供的操作符,要會(huì)自定義操作符
RxSwift的優(yōu)點(diǎn)
-
Composable
可組合蟀淮,在設(shè)計(jì)模式中有一種模式叫做組合模式最住,你可以方便的用不同的組合實(shí)現(xiàn)不同的類 -
Reusable
代碼可重用,原因很簡(jiǎn)單怠惶,對(duì)應(yīng)RxSwift
涨缚,就是一堆Obserable
-
Declarative
響應(yīng)式的,因?yàn)闋顟B(tài)不可變策治,只有數(shù)據(jù)變化 -
Understandable and concise
簡(jiǎn)潔脓魏,容易理解。 -
Stable
穩(wěn)定通惫,因?yàn)?code>RxSwift寫出的代碼茂翔,單元測(cè)試時(shí)分方便 -
Less stateful
“無(wú)”狀態(tài)性,因?yàn)閷?duì)于響應(yīng)式編程履腋,你的應(yīng)用程序就是一堆數(shù)據(jù)流 -
Without leaks
沒有泄漏珊燎,因?yàn)橘Y源管理非常簡(jiǎn)單