Bài 10. Thao Tác Lọc Trong RxSwift
1. Toán Tử Bỏ Qua
1.1. ignoreElements
Khi bạn không muốn nhận tất cả các phần tử từ một Observable, bạn có thể sử dụng toán tử ignoreElements
. Toán tử này sẽ bỏ qua tất cả các phần tử và chỉ cho phép nhận các sự kiện .completed
và .error
. Ví dụ:
swift
let subject = PublishSubject<String>()
let bag = DisposeBag()
subject
.ignoreElements()
.subscribe { event in
print(event)
}
.disposed(by: bag)
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onCompleted()
Kết quả:
completed
1.2. elementAt(
Toán tử này cho phép bạn lấy phần tử thứ n của Observable. Lưu ý rằng việc đánh số bắt đầu từ 0. Ví dụ:
swift
let subject = PublishSubject<String>()
let bag = DisposeBag()
subject
.elementAt(2)
.subscribe { event in
print(event)
}
.disposed(by: bag)
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onCompleted()
Kết quả:
next(3)
completed
1.3. filter{ }
Nếu bạn cần lấy nhiều phần tử hơn, bạn có thể sử dụng toán tử filter
. Đây là ví dụ:
swift
let bag = DisposeBag()
let array = Array(0...10)
Observable.from(array)
.filter { $0 % 2 == 0 }
.subscribe(onNext: {
print($0) })
.disposed(by: bag)
Kết quả:
0
2
4
6
8
10
2. Toán Tử Bỏ Qua
2.1. skip(: _ )
Toán tử này sẽ bỏ qua một số lượng phần tử nhất định. Ví dụ:
swift
let disposeBag = DisposeBag()
Observable.of("A", "B", "C", "D", "E", "F")
.skip(3)
.subscribe(onNext: {
print($0) })
.disposed(by: disposeBag)
Kết quả:
D
E
F
2.2. skip(while: _ )
Toán tử này bỏ qua các phần tử cho đến khi một điều kiện không còn đúng. Ví dụ:
swift
let bag = DisposeBag()
Observable.of(2, 4, 8, 9, 2, 4, 5, 7, 0, 10)
.skip(while: { $0 % 2 == 0 })
.subscribe(onNext: {
print($0) })
.disposed(by: bag)
Kết quả:
9
2
4
5
7
0
10
2.3. skip(until: _ )
Toán tử này bỏ qua các phần tử cho đến khi một Observable khác phát ra giá trị. Ví dụ:
swift
let bag = DisposeBag()
let subject = PublishSubject<String>()
let trigger = PublishSubject<String>()
subject
.skip(until: trigger)
.subscribe(onNext: { value in
print(value)
})
.disposed(by: bag)
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
trigger.onNext("XXX")
subject.onNext("4")
Kết quả:
4
3. Toán Tử Lấy Phần Tử
3.1. take( _ )
Toán tử này lấy một số lượng phần tử từ Observable. Ví dụ:
swift
let bag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
.take(4)
.subscribe(onNext: {
print($0)
})
.disposed(by: bag)
Kết quả:
1
2
3
4
3.2. take(while: _ )
Toán tử này lấy tất cả các giá trị cho đến khi điều kiện không còn đúng. Ví dụ:
swift
Observable.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
.take(while: { $0 < 4 })
.subscribe(onNext: { (value) in
print(value)
})
.disposed(by: bag)
Kết quả:
1
2
3
enumerated()
Toán tử này sẽ thêm chỉ số cho các giá trị. Ví dụ:
swift
Observable.of(2, 4, 6, 8, 0, 12, 1, 3, 4, 6, 2)
.enumerated()
.take(while: { index, value in
value % 2 == 0 && index < 3
})
.subscribe(onNext: { (value) in
print(value)
})
.disposed(by: bag)
Kết quả:
(index: 0, element: 2)
(index: 1, element: 4)
(index: 2, element: 6)
3.3. take(until: _ )
Toán tử này giúp bạn lấy các phần tử cho đến khi một Observable khác phát ra giá trị. Ví dụ:
swift
let bag = DisposeBag()
let subject = PublishSubject<String>()
let trigger = PublishSubject<String>()
subject
.takeUntil(trigger)
.subscribe(onNext: { value in
print(value)
})
.disposed(by: bag)
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
trigger.onNext("XXX")
subject.onNext("4")
Kết quả:
1
2
3
4. Toán Tử Khác Biệt
4.1. Equatable Type
Toán tử này lọc các giá trị trùng lặp liên tiếp. Ví dụ:
swift
let disposeBag = DisposeBag()
Observable.of("A", "A", "B", "B", "A", "A", "A", "C", "A")
.distinctUntilChanged()
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
Kết quả:
A
B
A
C
A
4.2. Custom Type
Bạn có thể sử dụng toán tử này với kiểu dữ liệu tùy chỉnh. Ví dụ:
swift
struct Point {
var x: Int
var y: Int
}
let disposeBag = DisposeBag()
let array = [Point(x: 0, y: 1), Point(x: 0, y: 2), Point(x: 1, y: 0)]
Observable.from(array)
.distinctUntilChanged { (p1, p2) -> Bool in
p1.x == p2.x
}
.subscribe(onNext: { point in
print("Point (\(point.x), \(point.y))")
})
.disposed(by: disposeBag)
Kết quả:
Point (0, 1)
Point (1, 0)
Kết Luận
rxSwift cung cấp nhiều toán tử hữu ích để xử lý các stream dữ liệu một cách linh hoạt. Việc nắm vững các toán tử này sẽ giúp bạn lập trình hiệu quả hơn với Reactive Programming trong Swift.
source: viblo