일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- HIG
- map
- 리팩토링
- Xcode
- 스위프트
- swiftUI
- SWIFT
- Clean Code
- clean architecture
- tableView
- 리펙터링
- 리펙토링
- rxswift
- UICollectionView
- uiscrollview
- uitableview
- ribs
- MVVM
- 클린 코드
- Observable
- Human interface guide
- collectionview
- Protocol
- 애니메이션
- Refactoring
- combine
- UITextView
- swift documentation
- RxCocoa
- ios
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[RxSwift] 5.Filtering Operators 본문
구독 요청시, filtering하는 연산자를 넣어서
이벤트(onNext)들을 filter하여 선택적인 emit을 하기위한 연산자
1. Ignoring operators
1) ignoreElements()
- next이벤트 금지 필터 (completed, error는 사용가능)
/// ignoreElements
example(of: "ignoreElements") {
// 1
let strikes = PublishSubject<String>()
let disposeBag = DisposeBag()
// 2
strikes
.ignoreElements()
.subscribe { _ in
print("You're out!")
}
.disposed(by: disposeBag)
strikes.onNext("X") // print : none of print
strikes.onCompleted() // print : You're out!
}
2) elementAt()
- 입력한 인덱스 번호만 이벤트 수신
example(of: "elementAt") {
let strikes = PublishSubject<String>()
let disposeBag = DisposeBag()
strikes
.elementAt(2) // 인덱스로 2번(3번째 추가한 아이템 선택)
.subscribe(onNext: { item in
print(item)
})
.disposed(by: disposeBag)
strikes.onNext("first")
strikes.onNext("second")
strikes.onNext("third") // print : third
}
3) filter
emit할 값에 대한 조건을 명시적으로 설정
example(of: "filter") {
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6)
.filter { $0 % 2 == 0 }
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
/* prints
2
4
6
*/
2. Skipping operators
1) skip(_:)
입력한 갯수만큼 이벤트를 skip
example(of: "skip") {
let disposeBag = DisposeBag()
Observable.of("A", "B", "C", "D", "E", "F")
.skip(3)
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
/* prints
D
E
F
*/
2) skipWhile
- 조건에 만족하는 것을 skip, 조건이 맞는 원소가 발견되고 그 값이 연속적이면 계속 skip, 단 1회성(휘발성)
- 아래 예제에서 최초의 값이 2로 나누어 떨어지지 않으면, 필터링 하지 않고 모두 emit
* 4값과 끝에 2값은 skip안되는 것을 확인
example(of: "skipWhile") {
let disposeBag = DisposeBag()
Observable.of(2, 2, 2, 3, 4, 4, 2)
.skipWhile { $0 % 2 == 0 }
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
/* prints
3
4
4
2
*/
3) skipUntil
또 다른 subject를 두어서, 이 이벤트가 발생하기 전까지 event들을 skip
example(of: "skipUntil") {
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
let trigger = PublishSubject<String>()
subject
.skipUntil(trigger)
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
subject.onNext("A")
subject.onNext("B")
trigger.onNext("X")
subject.onNext("C")
// print: C
}
3. Taking operators
1) take(_:)
입력한 갯수만큼만 이벤트 허용
example(of: "take") {
let disposeBag = DisposeBag()
// 1
Observable.of(1, 2, 3, 4, 5, 6)
// 2
.take(3)
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
/* prints
1
2
3
*/
2) takeWhile(_:)
특정 조건까지 emit
- enumerated() : index와 배열의 원소 값을 얻을 수 있게끔 설정
- map{ $0.element } : takeWhile()후의 값은 이미 배열을 순회한 값(enumerated를 사용했으므로 for문처럼 접근한 것)
즉, enumerated()로 인해서 takeWhile()의 결과는 현재 하나의 튜플형태
튜플에 한 원소에 하나씩 접근하기 위해서 map을 사용 하는 것
example(of: "takeWhile") {
let disposeBag = DisposeBag()
Observable.of(2, 2, 4, 4, 6, 6, 2)
.enumerated()
.takeWhile { index, integer in
integer % 2 == 0 && index < 3
}
// 원소에 접근하는 중요한 작업
.map { $0.element }
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
/* prints
2
2
4
*/
3) takeLast(_:)
완료가 되면 count만큼 이전의 이벤트 발생
4. Distinct operators
1) distinctUntilChanged()
중복값 방지
example(of: "distinctUntilChanged") {
let disposeBag = DisposeBag()
// 1
Observable.of("A", "A", "B", "B", "A")
// 2
.distinctUntilChanged()
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
/* prints
A
B
A
*/
2) distinctUntilChanged의 클로저 사용
- distinctUntilChanged
- 정수 발음을 문자열로 바꾼다음에 한 문자열이 다른에 문자열에 속해있다면 true를 반환하게끔 설정(true : emit하지 말라는 의미)
(단 바뀌는 지점 emit)
example(of: "distinctUntilChanged(_:)") {
let disposeBag = DisposeBag()
// formatter.string(from: 110) -> Optional("one hundred ten")
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
Observable<NSNumber>.of(10, 110, 20, 200, 210, 310)
.distinctUntilChanged { a, b in
print("a=\(formatter.string(from: a)!), b=\(formatter.string(from: b)!)")
guard let aWords = formatter.string(from: a)?.components(separatedBy: " "),
let bWords = formatter.string(from: b)?.components(separatedBy: " ")
else {
return false
}
var containsMatch = false
for aWord in aWords where bWords.contains(aWord) {
containsMatch = true
break
}
return containsMatch
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
/* prints
10
a=ten, b=one hundred ten
a=ten, b=twenty
20
a=twenty, b=two hundred
200
a=two hundred, b=two hundred ten
a=two hundred, b=three hundred ten
*/
5. 시간과 관련된 연산자
1) Debounce
- 주어진 시간 후 이벤트 emit
- x초 후에 가장 마지막 이벤트 emit
2) Throttle
- 이벤트 발생 시, 해당 이벤트 emit 후 이후 주어진 시간 동안의 다른 이벤트 무시하다가 해당 시간이 흐르면 가장 최신의 이벤트를 emit
* 사용 : 뷰 컨트롤러를 present할 때 중복으로 tap하는 것을 방지
*참조 : RxSwift: Reactive Programming with Swift, by raywenderlich team's book
'RxSwift > RxSwift 기본' 카테고리의 다른 글
[RxSwift] 7.Transforming Operators (0) | 2020.06.01 |
---|---|
[RxSwift] 6.Filtering Operators 실습 (0) | 2020.05.29 |
[RxSwift] 4. Observables and Subjects 실전 적용 (0) | 2020.05.25 |
[RxSwift] 3. Subjects (0) | 2020.05.22 |
[RxSwift] 2. Observables (0) | 2020.05.21 |