移动端 RxSwift iOS开发进阶 - RxSwift: Filter相关方法 镇长 2019-03-27 2023-11-02 前言
万丈高楼平地起,前面两篇地基已经建好,现在开始第一层。示例代码请移步Github RxSwift 4.4
从本篇开始接下来几篇文章会详细学习 RxSwift
中 Operators
,作为 Rx
编程的基石,可以使用它来转换,处理和响应事件。
Operators
分为四个部分:
Filtering Operators
:过滤
Transforming Operators
: 转换
Combing Operators
: 组合
Time-Based Operators
: 基于时间操作
接下来学习过滤相关的操作。
Filtering Operators 过滤操作分为四类:
分类
主要方法
说明
Ignoring Operators
ignoreElements
elementAt
filter
用于忽略一些元素
Skipping Operators
skip
skipWhile
skipUntil
Taking Operators
take
takeWhile
takeUntil
Distinct Operators
distinctUntilChange
distinctUntilChanged(_:)
从整体上了解要学习的内容,接下来详细分析各个操作作用,特点及区别联系。
Ignoring Operators ignoreElements
特点:忽略所有的 .next
事件元素,允许终止事件通过。如:.completed
和 .error
。是不是应该想起来什么?ignoreElements
实际上返回一个 Completable
。
①:表示源序列,可以被订阅 ②:表示操作及参数 ③:订阅
实例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 example(of: "ignoreElements" ) { let strikes = PublishSubject <String >() let disposeBag = DisposeBag () strikes .ignoreElements() .subscribe{_ in print ("You are out!" ) } .disposed(by: disposeBag) strikes.onNext("X" ) strikes.onNext("Y" ) strikes.onCompleted() }
elementAt
特点: 获取指定位置的元素。只要获取到指定位置的元素,订阅就终止。
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 example(of: "elementAt" ) { let strikes = PublishSubject <String >() let bag = DisposeBag () strikes .elementAt(2 ) .subscribe(onNext: { element in print ("\(element) - You are out!" ) }) .disposed(by: bag) strikes.onNext("X" ) strikes.onNext("Y" ) strikes.onNext("Z" ) }
filter
特点:ignoreElement
和 elementAt
过滤序列元素。有时不针对全部或单个元素操作。filter
提供了一个闭包,针对所有的元素,只要满足添加就可以输出。
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 example(of: "filter" ) { let bag = DisposeBag () Observable .of(1 , 2 , 3 , 4 , 5 , 6 ) .filter{ $0 % 2 == 0 } .subscribe(onNext: { print ($0 ) }) .disposed(by: bag) }
skip
特点: 跳过指定数量的元素。
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 example(of: "skip" ) { let bag = DisposeBag () Observable .of("A" , "B" , "C" , "D" , "E" , "F" ) .skip(3 ) .subscribe( onNext: { print ($0 ) }) .disposed(by: bag) }
skipWhile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 example(of: "skipWhile" ) { let bag = DisposeBag () Observable .of(2 , 2 , 3 , 4 , 4 ) .skipWhile { $0 % 2 == 0 } .subscribe(onNext: { print ($0 ) }) .disposed(by: bag) }
skipUntil
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 example(of: "skipUntil" ) { let bag = DisposeBag () let subject = PublishSubject <String >() let trigger = PublishSubject <String >() subject .skipUntil(trigger) .subscribe(onNext: { print ($0 ) }) .disposed(by: bag) subject.onNext("A" ) subject.onNext("B" ) trigger.onNext("X" ) subject.onNext("C" ) }
Taking Operators take
1 2 3 4 5 6 7 8 9 10 11 12 13 /// Taking 是与 Skipping 相反的操作。 /// 1. take: 获取几个元素 example(of: "take") { let bag = DisposeBag() Observable.of(4, 5, 6, 7, 8, 9) .take(3) // 获取三个元素 .subscribe(onNext: { print($0) }) .disposed(by: bag) // 输出: 4 5 6 }
takeWhile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 example(of: "takeWhile" ) { let bag = DisposeBag () Observable .of(2 , 2 , 4 , 4 , 6 , 6 ) .enumerated() .takeWhile({ index, integer in integer % 2 == 0 && index < 3 }) .map { $0 .element } .subscribe(onNext: { print ($0 ) }) .disposed(by: bag) }
takeUntil
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 /// 3. takeUntil: 与 skipUntil 类似 /// 持续获取源序列中元素,直到触发序列发送 .next 事件。 example(of: "takeUntil") { let bag = DisposeBag() // 1. let subject = PublishSubject<String>() let trigger = PublishSubject<String>() // 2. subject .takeUntil(trigger) .subscribe(onNext: { print($0) }) .disposed(by: bag) // 3. subject.onNext("A") subject.onNext("B") trigger.onNext("1") // 触发序列终止源序列 subject.onNext("C") // 输出:A B // 思考:是不是可以通过 takeUntil 监控 VC 的销毁。 }
Distinct Operators distinctUntilChanged
1 2 3 4 5 6 7 8 9 10 11 12 13 /// 1. distinctUntilChanged : 阻止下一个重复元素 /// 只阻止相邻重复元素。 example(of: "distinctUntilChanged") { let bag = DisposeBag() Observable.of("A", "A", "B", "B", "A") .distinctUntilChanged() .subscribe(onNext: { print($0) }) .disposed(by: bag) // 输出:A B A }
distinctUntilChanged(_:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 /// 2. distinctUntilChanged(_:) 自定义比较 example(of: "distinctUntilChanged(_:)") { let bag = DisposeBag() // 1 let formatter = NumberFormatter() formatter.numberStyle = .spellOut // 朗读形式,英文,例如:110 ==> ["one", "hundred", "ten"] // 2. 序列 Observable<NSNumber>.of(10, 110, 20, 200, 210, 310) // 3 .distinctUntilChanged { a, b in guard let aWords = formatter.string(from: a)?.components(separatedBy: " "), let bWords = formatter.string(from: b)?.components(separatedBy: " ") else {return false} print(aWords, bWords) var containsMatch = false for aWord in aWords where bWords.contains(aWord) { containsMatch = true break } return containsMatch /* 第一次:["ten"] ["one", "hundred", "ten"] ==> true, 跳过 110 第二次:["ten"] ["twenty"] ==> false 第三次:["twenty"] ["two", "hundred"] ==> false 第四次:["two", "hundred"] ["two", "hundred", "ten"] ==> true,跳过 210 第五次:["two", "hundred"] ["three", "hundred", "ten"] ==> true, 跳过 310 */ } // 订阅 .subscribe(onNext: { print($0) }) .disposed(by: bag) }