RxSwift 這個(gè)框架看我就夠了,這一篇我重點(diǎn)介紹高階函數(shù),掌握好
RxSwift
的高階函數(shù),是你通往成功的捷徑蜡峰。搞RxSwift
摔认,我是認(rèn)真的
RxSwift 寶圖鎮(zhèn)博,咔咔點(diǎn)贊~~~~
-
RxSwift 深入淺出(一)RxSwift初探
-
RxSwift 深入淺出(二)高階函數(shù)
-
RxSwift 深入淺出(三)Subject
-
RxSwift 深入淺出(四)控件應(yīng)用
-
RxSwift 深入淺出(五)tableView應(yīng)用
-
RxSwift 深入淺出(六)RxDataSources
-
RxSwift 深入淺出(七)網(wǎng)絡(luò)封裝
-
RxSwift 深入淺出(八)開(kāi)發(fā)總結(jié)
import Foundation
import RxSwift
import RxCocoa
class FilteringVC: UIViewController {
let disposedB = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.orange
// testFilter()
testDistinctUntilChanged()
// testSingle()
// testElementAt()
// testIgnoreElements()
// testTake()
// testTakeLast()
// testSkip()
// testSample()
// testDebounce()
}
func testFilter(){
//該操作符就是用來(lái)過(guò)濾掉某些不符合要求的事件。
Observable.of(2, 30, 22, 5, 60, 3, 40 ,9)
.filter {
$0 > 10
}
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
}
func testDistinctUntilChanged(){
//該操作符用于過(guò)濾掉連續(xù)重復(fù)的事件蚌卤。
Observable.of(2, 2, 2, 5, 60, 3, 40 ,9)
.distinctUntilChanged()
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
}
func testSingle(){
Observable.of(2, 30, 22, 5, 60, 3, 40 ,9)
.filter {
$0 > 10
}
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
}
func testElementAt(){
// 只發(fā)送你選定的那個(gè)元素
Observable.of(1, 2, 3, 4)
.elementAt(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
}
func testIgnoreElements(){
// 該操作符可以忽略掉所有的元素,只發(fā)出 error或completed 事件。
// 如果我們并不關(guān)心 Observable 的任何元素赎婚,只想知道 Observable 在什么時(shí)候終止,那就可以使用 ignoreElements 操作符樱溉。
Observable.of(1, 2, 3, 4)
.ignoreElements()
.subscribe{
print($0)
}
.disposed(by: disposedB)
}
func testTake(){
// 該方法實(shí)現(xiàn)僅發(fā)送 Observable 序列中的前 n 個(gè)事件挣输,在滿足數(shù)量之后會(huì)自動(dòng) .completed。
Observable.of(1, 2, 3, 4)
.take(1)
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
}
func testTakeLast(){
// 該方法實(shí)現(xiàn)僅發(fā)送 Observable序列中的后 n 個(gè)事件福贞。
Observable.of(1, 2, 3, 4)
.takeLast(1)
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
}
func testSkip(){
// 跳過(guò)源 Observable 序列發(fā)出的前 n 個(gè)事件撩嚼。
Observable.of(1, 2, 3, 4)
.skip(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
}
func testSample(){
// 通過(guò) notifier 的事件 - 會(huì)觸發(fā) source 的響應(yīng),而如果兩次 notifier 事件之間沒(méi)有源序列的事件挖帘,則不發(fā)送值完丽。
let source = PublishSubject<Int>()
let notifier = PublishSubject<String>()
source.sample(notifier)
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
source.onNext(1)
//讓源序列接收接收消息
notifier.onNext("A")
source.onNext(2)
//讓源序列接收接收消息
notifier.onNext("B")
notifier.onNext("C")
source.onNext(3)
source.onNext(4)
//讓源序列接收接收消息
notifier.onNext("D")
source.onNext(5)
//讓源序列接收接收消息
notifier.onCompleted()
}
func testDebounce(){
// debounce 操作符可以用來(lái)過(guò)濾掉高頻產(chǎn)生的元素,它只會(huì)發(fā)出這種元素:該元素產(chǎn)生后拇舀,一段時(shí)間內(nèi)沒(méi)有新元素產(chǎn)生逻族。
// 換句話說(shuō)就是,隊(duì)列中的元素如果和下一個(gè)元素的間隔小于了指定的時(shí)間間隔骄崩,那么這個(gè)元素將被過(guò)濾掉聘鳞。
// debounce 常用在用戶輸入的時(shí)候,不需要每個(gè)字母敲進(jìn)去都發(fā)送一個(gè)事件要拂,而是稍等一下取最后一個(gè)事件抠璃。
//
//定義好每個(gè)事件里的值以及發(fā)送的時(shí)間
let times = [ [ "value": 1, "time": 0.1 ],
[ "value": 2, "time": 1.1 ],
[ "value": 3, "time": 1.2 ],
[ "value": 4, "time": 1.2 ],
[ "value": 5, "time": 1.4 ],
[ "value": 6, "time": 2.1 ] ]
//生成對(duì)應(yīng)的 Observable 序列并訂閱
Observable.from(times)
.flatMap { item in
return Observable.of(Int(item["value"]!))
.delaySubscription(Double(item["time"]!), scheduler: MainScheduler.instance)
}
.debounce(0.5, scheduler: MainScheduler.instance) //只發(fā)出與下一個(gè)間隔超過(guò)0.5秒的元素
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
}
}
上面是經(jīng)常使用的高階函數(shù),其實(shí)和swift的高階函數(shù)是非常類(lèi)似的脱惰,下面再講幾個(gè)有意思的高階函數(shù)
class ViewController: UIViewController {
let disposedB = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
// testBuffer()
// testWindow()
// testMap()
// testFlatMap()
// testConcatMap()
// testGroupBy()
self.present(FilteringVC(), animated: true, completion: nil)
}
func testGroupBy(){
// groupBy 操作符將源 Observable 分解為多個(gè)子 Observable鸡典,然后將這些子 Observable 發(fā)送出來(lái)。
// 也就是說(shuō)該操作符會(huì)將元素通過(guò)某個(gè)鍵進(jìn)行分組枪芒,然后將分組后的元素序列以 Observable 的形態(tài)發(fā)送出來(lái)彻况。
Observable<Int>.of(1,2,3,4,5,6,7,8,9)
.groupBy(keySelector: { (element) -> String in
return element % 2 == 0 ? "偶數(shù)" : "基數(shù)"
})
.subscribe { (event) in
switch event{
case .next(let group):
group.asObservable()
.subscribe({ (event) in
print("event==\(event): \n key = \(group.key)")
})
.disposed(by:self.disposedB)
case .completed:
print("完成")
case .error(let myError):
print(myError)
}
}
.disposed(by:disposedB)
}
func testConcatMap(){
//concatMap 與 flatMap 的唯一區(qū)別是:當(dāng)前一個(gè) Observable 元素發(fā)送完畢后,后一個(gè)Observable 才可以開(kāi)始發(fā)出元素舅踪∨Ω剩或者說(shuō)等待前一個(gè) Observable 產(chǎn)生完成事件后,才對(duì)后一個(gè) Observable 進(jìn)行訂閱抽碌。
let subject1 = BehaviorSubject(value: "A")
let subject2 = BehaviorSubject(value: "1")
let variable = Variable(subject1) //這里裝進(jìn)去1
variable.asObservable()
.concatMap { $0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
subject1.onNext("B")
variable.value = subject2 //裝進(jìn)去2
subject2.onNext("2")
subject1.onNext("C")
/**
A
B
C ==>發(fā)現(xiàn)沒(méi)有打印 1,2的數(shù)據(jù),說(shuō)明了subject1還沒(méi)有完成
*/
subject1.onCompleted()
/**
A
B
C
2 //為什么沒(méi)有打印1 因?yàn)樵趦?chǔ)存訂閱的時(shí)候,發(fā)現(xiàn)1沒(méi)有訂閱,結(jié)果被2替換了儲(chǔ)存,之后訂閱,就能打印了
*/
}
func testFlatMap(){
// map 在做轉(zhuǎn)換的時(shí)候容易出現(xiàn)“升維”的情況悍赢。即轉(zhuǎn)變之后决瞳,從一個(gè)序列變成了一個(gè)序列的序列。
// 而 flatMap 操作符會(huì)對(duì)源 Observable 的每一個(gè)元素應(yīng)用一個(gè)轉(zhuǎn)換方法左权,將他們轉(zhuǎn)換成 Observables皮胡。 然后將這些 Observables 的元素合并之后再發(fā)送出來(lái)。即又將其 "拍扁"(降維)成一個(gè) Observable 序列赏迟。
// 這個(gè)操作符是非常有用的屡贺。比如當(dāng) Observable 的元素本生擁有其他的 Observable 時(shí),我們可以將所有子 Observables 的元素發(fā)送出來(lái)锌杀。
let subject1 = BehaviorSubject(value: "A")
let subject2 = BehaviorSubject(value: "1")
let variable = Variable(subject1) //這里裝進(jìn)去1
variable.asObservable()
.flatMap { $0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposedB)
subject1.onNext("B")
variable.value = subject2 //裝進(jìn)去2
subject2.onNext("2")
subject1.onNext("C")
//這樣12都能打印
}
func testMap(){
//該操作符通過(guò)傳入一個(gè)函數(shù)閉包把原來(lái)的 Observable 序列轉(zhuǎn)變?yōu)橐粋€(gè)新的 Observable 序列甩栈。
let subject = PublishSubject<String>()
subject.map { (str) -> String in
return str+"hello"
}
.subscribe(onNext: { (event) in
print(event)
}, onError: nil, onCompleted: {
print("完成了")
}) {
print("銷(xiāo)毀了")
}
.disposed(by: disposedB)
subject.onNext("Cooci")
}
func testWindow(){
// window 操作符和 buffer 十分相似。不過(guò) buffer 是周期性的將緩存的元素集合發(fā)送出來(lái)糕再,而 window 周期性的將元素集合以 Observable 的形態(tài)發(fā)送出來(lái)量没。
// 同時(shí) buffer要等到元素搜集完畢后,才會(huì)發(fā)出元素序列突想。而 window 可以實(shí)時(shí)發(fā)出元素序列殴蹄。
let subject = PublishSubject<String>()
subject.window(timeSpan: 2, count: 2, scheduler: MainScheduler.instance)
.subscribe(onNext: { (event) in
print(event)
}, onError: nil, onCompleted: {
print("完成了")
}) {
print("銷(xiāo)毀了")
}
.disposed(by: disposedB)
subject.onNext("111")
subject.onNext("222")
subject.onNext("333")
subject.onNext("aaa")
subject.onNext("bbb")
subject.onNext("ccc")
}
func testBuffer(){
//buffer 方法作用是緩沖組合,第一個(gè)參數(shù)是緩沖時(shí)間猾担,第二個(gè)參數(shù)是緩沖個(gè)數(shù)袭灯,第三個(gè)參數(shù)是線程。
//該方法簡(jiǎn)單來(lái)說(shuō)就是緩存 Observable 中發(fā)出的新元素垒探,當(dāng)元素達(dá)到某個(gè)數(shù)量妓蛮,或者經(jīng)過(guò)了特定的時(shí)間,它就會(huì)將這個(gè)元素集合發(fā)送出來(lái)圾叼。
let subject = PublishSubject<String>()
subject.buffer(timeSpan: 2, count: 2, scheduler: MainScheduler.instance)
.subscribe(onNext: { (event) in
print(event)
}, onError: nil, onCompleted: {
print("完成了")
}) {
print("銷(xiāo)毀了")
}
.disposed(by: disposedB)
subject.onNext("111")
subject.onNext("222")
subject.onNext("333")
subject.onNext("aaa")
subject.onNext("bbb")
subject.onNext("ccc")
//這里每?jī)擅氪蛴∫粋€(gè)事件
//["111", "222"]
// ["333", "aaa"]
// ["bbb", "ccc"]
// [] 當(dāng)所有事件完畢,不會(huì)有儲(chǔ)存事件,就會(huì)打印空
}
}
感謝 @蘑菇De大灰狼 點(diǎn)出博客存在的紕漏蛤克,同時(shí)歡迎大家點(diǎn)出,謝謝