就問此時此刻還有誰?45度仰望天空,該死!我這無處安放的魅力!swift
- RxSwift(1)— 初探
- RxSwift(2)— 核心邏輯源碼分析
- RxSwift(3)— Observable序列的建立方式
- RxSwift(4)— 高階函數(上)
- RxSwift(5)— 高階函數(下)
- RxSwift(6)— 調度者-scheduler源碼解析(上)
- RxSwift(7)— 調度者-scheduler源碼解析(下)
- RxSwift(8)— KVO底層探索(上)
- RxSwift(9)— KVO底層探索(下)
- RxSwift(10)— 場景序列總結
- RxSwift(11)— dispose源碼解析
- RxSwift(12)— Subject即攻也守
- RxSwift(13)— 爬過的坑
- RxSwift(14)— MVVM雙向綁定
RxSwift 目錄直通車 --- 和諧學習,不急不躁!bash
RxSwift
是一個很是好用的框架,若是你喜歡用Swift
開發,那麼RxSwift
是你不二的選擇,函數響應式的結果,讓你的代碼飛起來!在上癮RxSwift
給咱們帶來的便捷的同時,常常也會出現一些致命的坑,讓你怎麼也爬不出去,難受的一匹....歸其本質:你仍是對RxSwift
不夠了解,若是你想玩好RxSwift
,不妨花點時間靜下心來研究一下底層!這一篇文章給你們介紹幾點,平時在使用RxSwift
常常會遇到的坑app
首先有兩個頁面LGHomeViewController 首頁
和LGDetialViewController 詳情
,詳情頁面給首頁進行傳值,咱們能夠經過序列傳遞,達到你意想不到的快感,看代碼框架
LGDetialViewController 中ide
// 內部序列響應,不被外界影響
fileprivate var mySubject = PublishSubject<Any>()
var publicOB : Observable<Any>{
return mySubject.asObservable()
}
複製代碼
publicOB
,以便訂閱信息mySubject
序列響應,內部事件發送LGHomeViewController 中函數
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let vc = LGDetialViewController()
vc.publicOB
.subscribe(onNext: { (item) in
print("訂閱到 \(item)")
})
.disposed(by: disposeBag)
self.navigationController?.pushViewController(vc, animated: true)
}
複製代碼
push
到詳情頁面去上面的代碼乍一看沒有什麼問題,其實否則,這個過程不斷往首頁disposeBag
添加訂閱事件,會致使計數不斷增長,就是性能消耗源碼分析
*****LGDetialViewController出現了:RxSwift的引用計數: 37
****************************************
<_01_RxSwift-內存管理.LGDetialViewController: 0x7fa966414de0>走了
銷燬了
<_01_RxSwift-內存管理.LGPerson: 0x600001c8c6c0>銷燬釋放
text = Optional("Cooci")
*****LGDetialViewController出現了:RxSwift的引用計數: 38
****************************************
<_01_RxSwift-內存管理.LGDetialViewController: 0x7fa96665d280>走了
銷燬了
<_01_RxSwift-內存管理.LGPerson: 0x600001c93780>銷燬釋放
text = Optional("Cooci")
*****LGDetialViewController出現了:RxSwift的引用計數: 39
****************************************
複製代碼
complete
或者error
信號達到 :及時回收,這樣就不至於一直存在首頁的垃圾袋中override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// 頁面要退出,及時完成以便調用dispose
mySubject.onCompleted()
}
複製代碼
由於調用序列的完成函數,就會致使咱們的序列一次性,下次就沒法響應 解決辦法:從新激活post
fileprivate var mySubject = PublishSubject<Any>()
var publicOB : Observable<Any>{
// 重置激活
mySubject = PublishSubject<Any>()
return mySubject.asObservable()
}
複製代碼
咱們實際開發中避免不了使用tableView
,那麼在使用過程當中,常常會有一個坑:cell複用性能
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! LGTableViewCell
cell.button.rx.tap
.subscribe(onNext: { () in
print("點擊了 \(indexPath)")
})
.disposed(by: bag)
return cell
}
複製代碼
cell
的重用機制,會致使cell.button.rx.tap
的訂閱也會重複訂閱響應,顯然不是咱們正常開發中想見到的樣子點擊了 [0, 0]
********************
點擊了 [0, 1]
********************
點擊了 [0, 2]
********************
點擊了 [0, 1]
點擊了 [0, 21]
********************
點擊了 [0, 3]
點擊了 [0, 23]
********************
點擊了 [0, 29]
點擊了 [0, 49]
點擊了 [0, 69]
********************
複製代碼
cell.disposeBag
,在咱們重用響應的時候,及時銷燬,重置!// 外界訂閱處理
cell.button.rx.tap
.subscribe(onNext: { () in
print("點擊了 \(indexPath)")
})
.disposed(by: cell.disposeBag)
// cell內部處理
override func prepareForReuse() {
super.prepareForReuse()
// 銷燬垃圾袋重置
disposeBag = DisposeBag()
}
複製代碼
銷燬垃圾袋交給cell
自身學習
在prepareForReuse
響應的時候,銷燬垃圾袋重置
效果很明顯,問題獲得瞭解決!
思路二:基類封裝
class LGCustomCell: UITableViewCell{
var disposeBag = DisposeBag()
override func prepareForReuse() {
super.prepareForReuse()
disposeBag = DisposeBag()
}
}
複製代碼
做爲一個牛逼的開發人員,往往想到在
tableView
中處理響應都須要重寫prepareForReuse
,我就以爲難受,此刻我要勇敢的說:RxSwift
其實你能夠更好
因而我帶着不將就的心態構建咱們的思路三和思路四
extension Reactive where Base: UITableViewCell {
// 提供給外界重用序列
public var prepareForReuse: RxSwift.Observable<Void> {
var prepareForReuseKey: Int8 = 0
if let prepareForReuseOB = objc_getAssociatedObject(base, &prepareForReuseKey) as? Observable<Void> {
return prepareForReuseOB
}
let prepareForReuseOB = Observable.of(
sentMessage(#selector(Base.prepareForReuse)).map { _ in }
, deallocated)
.merge()
objc_setAssociatedObject(base, &prepareForReuseKey, prepareForReuseOB, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
return prepareForReuseOB
}
// 提供一個重用垃圾回收袋
public var reuseBag: DisposeBag {
MainScheduler.ensureExecutingOnScheduler()
var prepareForReuseBag: Int8 = 0
if let bag = objc_getAssociatedObject(base, &prepareForReuseBag) as? DisposeBag {
return bag
}
let bag = DisposeBag()
objc_setAssociatedObject(base, &prepareForReuseBag, bag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
_ = sentMessage(#selector(Base.prepareForReuse))
.subscribe(onNext: { [weak base] _ in
let newBag = DisposeBag()
guard let base = base else {return}
objc_setAssociatedObject(base, &prepareForReuseBag, newBag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
})
return bag
}
}
複製代碼
prepareForReuse
,只要發現咱們的cell
已發生重用,經過RxSwift
就會接受到一個重用序列的響應,起到綁定效果cell
的銷燬序列,畢竟cell
都銷燬了也就沒有任何響應的意義cell.button.rx.tap.takeUntil(cell.rx.prepareForReuse)
.subscribe(onNext: { () in
print("點擊了 \(indexPath)")
})
複製代碼
takeUntil
限定了button
的點擊響應能力cell.button.rx.tap
.subscribe(onNext: { () in
print("點擊了 \(indexPath)")
})
.disposed(by: cell.rx.reuseBag)
複製代碼
cell
的重寫響應,一旦有重寫那麼就直接銷燬重置,達到自動重置效果
2019年08月10日 01:33
還在堅持把博客寫完,這一年一直在不斷更新博客內容(由於以前一直忙還有本身惰性都沒有好好更新)看到不少博主都是粉絲幾千,心裏也不免失落。悟已往之不諫,知來者之可追! 接下來會持續努力和你們一塊兒共建iOS
生態強盛。我仍是我,顏色不同的煙火,我是Cooci
,我爲本身帶鹽!就問此時此刻還有誰?45度仰望天空,該死!我這無處安放的魅力!