02. RxSwift (2) ———— Basic Operations

It will take about 5 minutes to finish reading this article.

1. DisposeBag

Garbage collection bag, DisposeBag is actually equivalent to ARC in iOS, it will destroy the observer at the appropriate time, a memory management mechanism of RxSwift.

1
let disposeBag = DisposeBag()

2. Common basic operations

2.1 never

never is a special entity used to create an Observable that never terminates. This Observable will not emit any elements, nor will it emit error or completion events. Typically used to indicate a situation that persists but does not emit any events. Because it never terminates, care needs to be taken when subscribing to take appropriate steps to handle unsubscription situations.

1
2
3
4
5
6
func example00() {
Observable<String>.never()
.subscribe { _ in
print("This will not be executed here...")
}.disposed(by: disposeBag)
}

2.2 empty

Used to create an empty Observable that does not emit any elements or events, i.e. it is an Observable that completes immediately. Usually used to indicate that the result of some operation is empty or does not produce any value. The sequence created by empty can only emit one completed event.

1
2
3
4
5
6
7
8
func example01() {
Observable<Int>.empty()
.subscribe { event in
print(event)
}.disposed(by: disposeBag)
}
//Result:
completed

2.3 just

It is used to create an Observable sequence containing only a single element. just takes an argument and emits that argument as an element, creating an Observable containing a single element. Typically used to convert a single value or object to an Observable.

1
2
3
4
5
6
7
8
9
func example02() {
Observable.just("?")
.subscribe { event in
print(event)
}.disposed(by: disposeBag)
}
//Result:
next(?)
completed

2.4 of

Used to pass multiple elements as parameters, and then emit these elements in sequence to create an Observable sequence containing these elements. This operator is ideal for creating an Observable containing static data.

1
2
3
4
5
6
7
8
9
10
11
func example03() {
Observable.of("?", "?", "?", "?")
.subscribe(onNext: { element in
print(element)
}).disposed(by: disposeBag)
}
//Result:
?
?
?
?

If you remove onNext: above, the result will be like this, which corresponds to our subscribe. Subscribe only listens for events. The execution results are as follows:

1
2
3
4
5
next(?)
next(?)
next(?)
next(?)
completed

2.5 from

Used to convert an array, sequence, or enumerable object into an Observable, emitting its elements in sequence. It is suitable for converting an existing collection of data into an observable sequence.

1
2
3
4
5
6
7
8
9
10
func example04() {
Observable.from(["1", "2", "3", "4"])
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
}
//Result:
1
2
3
4

2.6 create

Method for creating a custom Observable. The create method gives you complete control over the behavior of the Observable, including when to emit element, error, or completion events. This allows you to create highly customized Observables to meet specific needs.

The create operator passes in an observer, and then calls the observer’s onNext, onCompleted, and onError methods. Returns an observable sequence.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func example05() {
let myJust = { (element: String) -> Observable<String> in
return Observable.create { observer in
observer.on(.next(element))
observer.on(.completed)
return Disposables.create()
}
}

myJust("?")
.subscribe { print($0) }
.disposed(by: disposeBag)
}
//Result:
next(?)
completed

2.7 range

Factory function for creating an Observable that emits a sequence of integers within a range. The range operator generates an Observable sequence that emits consecutive integers starting at a specified starting value until a specified number or ending value is reached.

1
2
3
4
5
6
7
8
9
10
11
12
func example06() {
Observable.range(start: 3, count: 5)
.subscribe { print($0) }
.disposed(by: disposeBag)
}
//Result:
next(3)
next(4)
next(5)
next(6)
next(7)
completed

2.8 repeatElement

Factory function for creating an Observable that emits the specified element repeatedly indefinitely. It generates a sequence of Observables that emit the same elements until you explicitly stop it.

1
2
3
4
5
6
7
8
9
10
func example07() {
Observable.repeatElement("#")
.take(3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
}
//Result:
#
#
#

2.9 generate

Generates elements in an Observable sequence according to specified logic, and allows you to customize how the elements are generated. The generate operator allows you to define the starting state of generated elements, incrementing logic, and when to terminate generation. The observable sequence created by generate will emit the corresponding event when the initialization condition is true.

1
2
3
4
5
6
7
8
9
10
11
12
13
func example08() {
Observable.generate(
initialState: 0,
condition: { $0 < 3 },
iterate: { $0 + 1 }
)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
}
//Result
0
1
2

2.10 deferred

Used to delay the creation of an Observable until an observer subscribes to it. This means that every time an observer subscribes, the specified closure is executed to create a new Observable. Note: Deferred will create a new observable sequence for each subscriber observer.

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
func example09() {
var count = 1
let deferredSequence = Observable<String>.deferred {
print("Creating \(count)")
count += 1

return Observable.create { observer in
print("Emitting...")
observer.onNext("?")
observer.onNext("?")
observer.onNext("?")
return Disposables.create()
}
}

deferredSequence
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

deferredSequence
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
}
//Result
Creating 1
Emitting...
?
?
?
Creating 2
Emitting...
?
?
?

In the above example, a new deferredSequence will be created every time you subscribe, so Emitting will be printed twice.

2.11 error

Indicates that an error occurred during the Observable’s life cycle. When an Observable encounters an error condition that prevents it from continuing to emit elements normally, it emits an error event and passes the error information to the observer. It creates an observable sequence but does not emit any normal events, only the error event and ends.

1
2
3
4
5
6
7
func example10() {
Observable<Int>.error(TestError.test) //Custom Error subclasses
.subscribe { print($0) }
.disposed(by: disposeBag)
}
//Result:
error(test)

2.12 doOn

Used to add a side-effect behavior that performs a specified operation when certain events in the Observable’s life cycle occur, but does not change the elements in the Observable.

The feeling of doOn is to execute a certain method first when directly processing onNext. The doOnNext(:) method is called before subscribe(onNext:), and doOnCompleted(:) is called before subscribe(onCompleted:).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func example11() {
Observable.of("1", "2", "3", "4")
.do(onNext: { print("Intercepted:", $0) }, onError: { print("Intercepted error:", $0) }, onCompleted: { print("Completed") })
.subscribe(onNext: { print($0) },onCompleted: { print("Finished") })
.disposed(by: disposeBag)
}
//Result:
Intercepted: 1
1
Intercepted: 2
2
Intercepted: 3
3
Intercepted: 4
4
Completed
Finished