I’ll build on that by introducing some common functions and practical tips. First, this article describes the actions used to filter next events. These filtering operations are similar to the filter operations in the Swift standard library. It allows us to filter out those that don’t fit the criteria before we actually start doing business, and this paradigm of functional programming opens our minds.
Ignore filter
The simplest and most straightforward filtering operation in RxSwift is ignoreElements. This operation masks all next events and only focuses on error and Completed events. As shown in the figure below, all next of the observable is filtered throughout its life cycle.
Sample code:
let strikes = PublishSubject<String> ()let disposeBag = DisposeBag()
strikes
.ignoreElements()
.subscribe { _ in
print("You're out!")
}
.addDisposableTo(disposeBag)
strikes.onNext("X")
strikes.onNext("X")
strikes.onNext("X")
strikes.onCompleted()
/* You're out! * /Copy the code
But instead of filtering all the brutality, sometimes we just need to filter specific incidents. For example, we can filter the specific index number next through elementAt. The following figure illustrates an elementAt operation that responds only to the second next event.
The corresponding code is:
let strikes = PublishSubject<String> ()let disposeBag = DisposeBag()
strikes
.elementAt(2)
.subscribe(onNext: { str in
print(str)
})
.addDisposableTo(disposeBag)
strikes.onNext("1")
strikes.onNext("2")
strikes.onNext("3")
strikes.onCompleted()
/* Prints the result 3 */Copy the code
The above two operations will end up targeting at most one next event, but most of the time we need to filter out a set of next events that meet the criteria. The following figure illustrates the operation using filter to filter data less than 3.
The corresponding codes are shown as follows:
let strikes = PublishSubject<Int> ()let disposeBag = DisposeBag()
strikes
.filter{$0 < 3 }
.subscribe(onNext: { num in
print("\(num)")
})
.addDisposableTo(disposeBag)
strikes.onNext(1)
strikes.onNext(2)
strikes.onNext(3)
strikes.onNext(4)
strikes.onNext(5)
strikes.onCompleted()
/* Prints the result 1 2 */Copy the code
Skip the filter
In addition to ignoring operations, another common filter is skipping operations. Of all the skip operations, skip is the simplest. By setting parameters, we can skip a specified number of events with a simple implementation. For example, the following illustration shows skipping the first two events.
let strikes = PublishSubject<Int> ()let disposeBag = DisposeBag()
strikes
.skip(2)
.subscribe(onNext: { num in
print("\(num)")
})
.addDisposableTo(disposeBag)
strikes.onNext(1)
strikes.onNext(2)
strikes.onNext(3)
strikes.onNext(4)
strikes.onNext(5)
strikes.onCompleted()
/* Prints the result 3 4 5 */Copy the code
Of course, we can still do something like filter with skipWhile, except skip the event with the specified index number. It’s just that the filter will filter qualifying events throughout its life cycle, whereas the skipWhile stops working after it finds the first event that doesn’t qualify for a skip operation. For example, in the following skipWhile, the condition is that the data will be skipped if it is odd, but after data 2 is executed, data 3 will not be skipped even though it is odd. So strictly speaking skipWhile can be a bit ambiguous, in fact it skips all qualifying events until it finds the first event that can be executed.
Here is the skipWhile code to skip even numbers:
let strikes = PublishSubject<Int> ()let disposeBag = DisposeBag()
strikes
.skipWhile{ num in
num % 2= =0
}
.subscribe(onNext: { num in
print("\(num)")
})
.addDisposableTo(disposeBag)
strikes.onNext(2)
strikes.onNext(2)
strikes.onNext(3)
strikes.onNext(4)
strikes.onNext(5)
strikes.onCompleted()
/* Prints the result 3 4 5 */Copy the code
So far, the filtering operations above have been based on static conditions. What if now you need to filter judgments based on the behavior of other observable instances? So we’ll look at dynamic judgments involving multiple instances, the most common of which is the skipUntil operation. The top two rows represent the life cycle of the observable and the bottom row represents the observer. The observer in the third row does not receive the data in the first row until the observable in the second row sends the data.
Corresponding code in the diagram:
let strikes = PublishSubject<String> ()let trigger = PublishSubject<String> ()let disposeBag = DisposeBag()
strikes
.skipUntil(trigger)
.subscribe(onNext: {
print($0)
})
.addDisposableTo(disposeBag)
strikes.onNext("1")
trigger.onNext("X")
strikes.onNext("2")
strikes.onNext("3")
strikes.onCompleted()
/* Prints the result 2 3 */Copy the code
Take the filter
This is a set of filtering operations as opposed to Skip. The most basic operation in this group of operations is take, which is completely opposite to skip. The take(2) operation, shown below, responds only to the first two events and ignores the later ones.
The corresponding code in the figure above:
let strikes = PublishSubject<String> ()let disposeBag = DisposeBag()
strikes
.take(2)
.subscribe(onNext: {
print($0)
})
.addDisposableTo(disposeBag)
strikes.onNext("1")
strikes.onNext("2")
strikes.onNext("3")
strikes.onCompleted()
/* Prints the result 1 2 */Copy the code
In addition, skipWhile also has a corresponding Take operation takeWhile. The code structure of the two is almost the same except that the former skips while the latter responds. Instead of introducing the takeWhile operation (you can try it yourself), I will introduce the takeWhile variant takeWhileWithIndex. In fact, the name of the function indicates the main function of the operation, and the index parameter is added to the base of the takeWhile. Because sometimes we need to filter judgment by value, index may also be a judgment dimension. The following figure shows a simple use example of takeWhileWithIndex. Events with value and index values less than 1 are skipped.
Corresponding code in the diagram:
let strikes = PublishSubject<Int> ()let disposeBag = DisposeBag()
strikes
.takeWhileWithIndex { integer, index in
integer > 1 && index > 1
}
.subscribe(onNext: {
print( "\ [$0)")
})
.addDisposableTo(disposeBag)
strikes.onNext(1)
strikes.onNext(2)
strikes.onNext(3)
strikes.onCompleted()
/* Prints the result 3 */Copy the code
In fact, Skip group also has the skipWhileWithIndex, which is opposite to takewhileIndex. Next, Take until, the last operation in the Take group. Again, this operation is the reverse of skipUntil, and the observer of that instance object will not stop responding until another instance object is fired. The following is a simple example of a takeUntil operation, in which the third row responds to the data sent by the first observable until the second row is triggered.
Corresponding code:
let strikes = PublishSubject<String> ()let trigger = PublishSubject<String> ()let disposeBag = DisposeBag()
strikes
.takeUntil(trigger)
.subscribe(onNext: {
print($0)
})
.addDisposableTo(disposeBag)
strikes.onNext("1")
strikes.onNext("2")
trigger.onNext("X")
strikes.onNext("3")
strikes.onCompleted()
/* Prints the result 1 2 */Copy the code
Distinct filter
Finally, this article describes the Distinct filter operation distinctUntilChanged. For the observer, sometimes the same data may occur consecutively over a certain period of time. Assuming the data is uI-specific, there is no need to refresh. Therefore, it is necessary to filter these continuous same data and reduce unnecessary response operations. Here is a simple example where we filter out the same subsequent data and only respond to the first one.
Corresponding sample code:
let strikes = PublishSubject<String> ()let disposeBag = DisposeBag()
strikes
.distinctUntilChanged()
.subscribe(onNext: {
print($0)
})
.addDisposableTo(disposeBag)
strikes.onNext("1")
strikes.onNext("2")
strikes.onNext("2")
strikes.onNext("3")
strikes.onCompleted()
/* Prints the result 1 2 3 */Copy the code
conclusion
This article builds on the previous steps by illustrating and illustrating the main filtering operations. Mastering these operations will help us maximize the power of RxSwift. Of course, the code in this article is very simple, so I encourage you to hone your skills in actual programming.
The original address