作為一個iOS開發(fā)人員, 當
Swift遇上了RxSwift--> 函數(shù)響應(yīng)式編程,在沒有認識RxSwift之前,可能是一臉的懵逼,即使偶爾使用一下也是丈二的和尚莫不著頭腦,胡亂使用,但是當你認識了解并深入探索以后,你會對RxSwift愛不釋手,甚至忘記最初代碼的寫法!?。?!
函數(shù)響應(yīng)式編程
1. 函數(shù)式 :
-
函數(shù)式編程不是一種技術(shù),而是一種高級抽象的編程思想設(shè)計,簡稱FP(Functional Programming),函數(shù)一詞就直觀的體現(xiàn)了這就是一個數(shù)學(xué)運算方法。它又分為兩種形式:
- 無副作用:函數(shù)沒有變量,這種純粹的函數(shù)式編程語言,一旦輸入確定,那么輸出就是確定的,它是沒有副作用的。
- 有副作用:函數(shù)有變量,這種函數(shù)式編程語言它的輸入會隨著變量不斷的變化,最后的輸出也就不確定,它是存在副作用的。
函數(shù)表達式 :y = f(x) ---> x = f(x) ---> y = f(f(x))
廢話不多說,直接實例感受一把:
/**
1. 首先獲取 > 3的數(shù)字
2. 獲取的數(shù)字之后 + 1
3.所有數(shù)字中的偶數(shù)
*/
let array = [1,2,3,4,5,6,7,8,9,10]
for num in array{
if num > 3{
let number = num + 1
if (number % 2 == 0) {
print(number)
}
}
}
/**
以上代碼看起來沒有任何問題,確實也毛病,但是:
* 上面的代碼嵌套層次之深,讓人感覺非常惡心
* 代碼的可讀性也是非常差的
* 代碼復(fù)用性較低
* 維護以及代碼構(gòu)建成本太高
*/
//這樣就成了函數(shù)式出現(xiàn)的必要性:
array.filter{ $0 > 3}
.filter{ ($0+1) % 2 == 0 }
.forEach { print($0) }
/**
* 代碼層次非常清晰
* 代碼可讀性高
* 代碼復(fù)用性高
* 代碼簡潔,直接面向開發(fā)需求
*/
2. 響應(yīng)式 :
-
響應(yīng)式編程是一種基于異步數(shù)據(jù)流概念的編程模式。數(shù)據(jù)流就像一條河:它可以被觀測,被過濾,被操作,或者為新的消費者與另外一條流合并為一條新的流。響應(yīng)式編程的一個關(guān)鍵概念是事件。事件可以被等待,可以觸發(fā)過程,也可以觸發(fā)其它事件 - 而iOS原生開發(fā)中,觸發(fā)對象與響應(yīng)方法是分離的,如
button的初始化和點擊響應(yīng)方法是分離的。類似的還有tap、textField、textView、notifaction、KVO、NSTimer等等。
RxSwift來源
RxSwift 是 Rx家族 的重要一員,Rx就是復(fù)合的代名詞, 不僅僅是一種使用可觀察數(shù)據(jù)流進行異步編程的接口,他更是一種編程思想理念的突破實踐。它集結(jié)了多種編程模式和精華于一身,包括:觀察者模式,迭代器,函數(shù)響應(yīng)式編程等待。 RxSwift作為Rx家族的一員,一樣繼承了Rx的這一系列的特性。
RxSwift優(yōu)勢
-
RxSwift是Swift函數(shù)響應(yīng)式編程的一個開源庫:github地址, 其目的就是讓可觀察數(shù)據(jù)流、異步編程能夠更好序列化,使用swift進行函數(shù)響應(yīng)式編程。 - 它拓展了觀察者模式,使你能夠自由組合多個異步事件,而不需要去
關(guān)心線程,同步,線程安全,并發(fā)數(shù)據(jù)以及I/O阻塞。 -
RxSwift是Rx為Swift語言開發(fā)的一門函數(shù)響應(yīng)式編程語言, 它可以代替iOS系統(tǒng)的Target Action,代理,閉包,通知,KVO,同時還提供網(wǎng)絡(luò),數(shù)據(jù)綁定,UI事件處理,UI的展示和更新,多線程……
RxSwift學(xué)習(xí)必要性
- 復(fù)合 - Rx 就是和復(fù)合的代名詞
- 復(fù)?用 - 復(fù)?用性?比較強 - 代碼量量降低
- 清晰 - 因為聲明都是不不可變更更,代碼函數(shù)式編程可讀性強
- 易易?用 - 理理解容易易,還抽象的了了異步編程,統(tǒng)?代碼?風(fēng)格
- 穩(wěn)定 - 因為 Rx 是完全通過單元測試的
RxSwift初識
1.KVO
//MARK: - KVO-原始三部曲
//1.添加觀察者
self.person.addObserver(self, forKeyPath: "name", options: .new, context: nil)
//2.實現(xiàn)觀察者方法
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("響應(yīng)")
print(change as Any)
}
//3.移除觀察者
deinit {
self.person.removeObserver(self, forKeyPath: "name")
}
//MARK: - RxSwift應(yīng)用-KVO
func setupKVO() {
self.person.rx.observeWeakly(String.self, "name")
.subscribe(onNext: { (value) in
print(value as Any)
})
.disposed(by: disposeBag)
}
2.UI層
- UIButton
//MARK: - button原始是寫法
self.button.addTarget(self, action: #selector(click), for: .touchUpInside)
func click() {
print("點擊")
}
//MARK: - RxSwift應(yīng)用-button響應(yīng)
func setupButton() {
self.button.rx.tap
.subscribe(onNext: { () in
print("點擊來了")
})
.disposed(by: disposeBag)
//上面的代碼和下面的意思一樣
self.button.rx.controlEvent(.touchUpInside)
.subscribe(onNext: { () in
print("點擊了")
})
.disposed(by: disposeBag)
}
- UITextFiled
//MARK: - RxSwift應(yīng)用-textfiled
func setupTextFiled() {
// 我們?nèi)绻獙斎氲奈谋具M行操作 - 比如輸入的的內(nèi)容 然后我們獲取里面的偶數(shù)
// self.textFiled.delegate = self
// 感覺是不是特別惡心
// 下面我們來看看Rx
self.textFiled.rx.text.orEmpty.changed.subscribe(onNext: { (text) in
print("監(jiān)聽到了 - \(text)")
}).disposed(by: disposeBag)
self.textFiled.rx.text.bind(to: self.button.rx.title()).disposed(by: disposeBag)
}
- UIScrollView
//MARK: - RxSwift應(yīng)用-scrollView
func setupScrollerView() {
scrollView.rx.contentOffset
.subscribe(onNext: { [weak self](content) in
self?.view.backgroundColor = UIColor.init(red: content.y/255*0.8, green: content.y/255*0.6, blue: content.y/255*0.3, alpha: 1)
})
.disposed(by: disposeBag)
}
- Tap手持
//MARK: - 手勢
func setupGestureRecognizer(){
let tap = UITapGestureRecognizer()
self.label.addGestureRecognizer(tap)
self.label.isUserInteractionEnabled = true
tap.rx.event.subscribe(onNext: { (tap) in
print(tap.view)
})
.disposed(by: disposeBag)
}
3.通知
//MARK: - 通知
func setupNotification(){
NotificationCenter.default.rx
.notification(UIResponder.keyboardWillShowNotification)
.subscribe { (event) in
print(event)
}.disposed(by: disposeBag)
}
4.NSTimer
//MARK: - RxSwift應(yīng)用-timer定時器
func setupTimer() {
timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
timer.subscribe(onNext: { (num) in
print("hello word \(num)")
}).disposed(by: disposeBag)
}
5.網(wǎng)絡(luò)
//MARK: - RxSwift應(yīng)用-網(wǎng)絡(luò)請求
func setupNextwork() {
let url = URL(string: "https://www.baidu.com")
URLSession.shared.rx.response(request: URLRequest(url: url!))
.subscribe(onNext: { (response, data) in
print("response ==== \(response)")
print("data ===== \(data)")
}, onError: { (error) in
print("error ===== \(error)")
}).disposed(by: disposeBag)
}
Rx 以前:
- KVO三部曲很惡心,不直觀
- UI層 需要設(shè)置
代理或者addTarget,代碼邏輯與事件邏輯分層- 通知的實現(xiàn),也是比較友善的:編程習(xí)慣都有在RxSwift風(fēng)格里面保留,降低了開發(fā)門檻
- 手勢看是去還是很不爽,還是需要添加到視圖上,可擴展一層再次處理,這樣就好了
- Timer根據(jù)創(chuàng)建受RunLoop影響,還要手動銷毀,還可能有線程問題
Rx 以后:
RxSwift溫柔的一句代碼搞定,腰也不疼了,腿也不酸了,一口氣直接上6樓,timer還不受RunLoop影響了,也不用手動管理了,線程這些也都安全了
總結(jié)
- 簡單的
rx體驗,就能讓人感覺,真的是處處皆rx,而且清晰簡潔,分段式操作,函數(shù)式響應(yīng)。對比原始寫法,一個字爽~把函數(shù)響應(yīng)式玩到了高潮!無論從代碼量,還是從代碼的可讀性,抑或代碼的復(fù)用性......都是大大優(yōu)化!
圖片.png
