https://utemissov.com/intro-to-rxswift-part-3/

This is the continuation of previous part 3. In this part we will cover

  1. startWith operator
  2. concat operator (instance and static)
  3. concatMap operator
  4. Difference b/w concatMap and flatMap operator
  5. merge
  6. combineLatest operator in detail with practical example

startWith

Prepends / start / Initialize a sequence of values to an observable sequence as shown in Figure we start the observable sequence with A and after subscription we observable emit value to its subscriber

concat (instance method)

Concatenates the second observable sequence to `self` upon successful termination of `self`

As shown in Figure 1 after the termination of obsB(self) it Concatenated obsA and obsB

Figure 1

As shown in Figure 2 concat operator didn’t trigger since subject is not terminated yet

Figure 2
Figure 3

Note: Observable sequences are strongly typed. You can only concatenate sequences whose elements are of the same type! If you try to concatenate sequences of different types, brace yourself for compiler errors. The Swift compiler knows when one sequence is an Observable<String> and the other an Observable<Int> so it will not allow you to mix them.

concat (static method)

The Observable.concat(_:) static method takes an ordered collection of observables (i.e. an array). It subscribes to the first sequence of the collection, relays its elements until it completes, then moves to the next one. The process repeats until all the observables in the collection have been used. If at any point an inner observable emits an error, the concatenated observable in turns emits the error and terminates

Figure 4

Difference B/W concatMap and flatMap

concatMap

concatMap(_:), closely related to flatMap(_:) which you discussed in Part2. The closure you pass to flatMap(_:) returns an Observable sequence which is subscribed to, and the emitted observables are all merged in random order

concatMap(_:) also take the closure you pass returns an Observable sequence which is subscribed to, and the emitted observables are all merged in sequential order 😕

As shown in Figure 5 flatMap iterate and subscribed to inner observable which in our case “German cities” and “Spanish cities” in sequence array and as these sequence emitted values it send it to the observer like normal flatten observable emit . Few things to note

  1. flatMap at a time can subscribed to multiple inner observable
  2. As shown in the console in Figure 5 the order of the cities is not guaranteed
Figure 5

As shown in Figure 6 same results but few things different from flatMap

  1. concatMap(_:) guarantees that each sequence produced by the closure will run to completion before the next is subscribed to. concatMap(_:) is therefore a handy way to guarantee sequential order.
  2. As shown in the console in Figure 5 the order of the cities is guaranteed
Figure 6

As shown in Figure 7 concatMap will not subscribe to “Spanish cities” observable until the subject will complete and when I tapped on button it terminated the subject and then concatMap triggered

Figure 7

where flatMap don’t depend upon the termination of subject

Figure 8

merge

combine multiple Observables into one by merging their emission. Same as concat but here the emission of element is priority

You can combine the output of multiple Observables so that they act like a single Observable, by using the Merge operator.

Merge may interleave the items emitted by the merged Observables (a similar operator, Concat, does not interleave items, but emits all of each source Observable’s items in turn before beginning to emit items from the next source Observable).

http://reactivex.io/documentation/operators/merge.html
  1. merge() completes after its source sequence completes and all inner sequences have completed.
  2. The order in which the inner sequences complete is irrelevant.
  3. If any of the sequences emit an error, the merge() observable immediately relays the error, then terminates.

combineLatest

Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element When any observable emits a value, emit the last emitted value from each.

In our case when A is emitted by subject1 it tries to emit last value of each observable since subject2 is empty it stops the event. When subject2 emit B it check whether all observable has any value and if that the case it will emitted the last value of each observable and called the closure with parameter having all the last/latest value of each observable and in that closure we can specified custom combining operation. This custom combination is also an observable which anyone can subscribed to it

Figure 9

combineLatest will not emit an initial value until each observable emits at least one value. As shown in Figure 10 since Subject2 is not initialized yet combineLatest will not called closure.

Figure 10

This has many concrete applications, such as observing several text fields at once and combining their values, watching the status of multiple sources, and so on and as shown below we added validation by taking both labels last text value and added validation .

In Short
→ combine observables using a closure receiving the latest value of each sequence as arguments. In this example, the combination is the concatenated string of both left and right values. It could be anything else that you need, as the type of the elements emitted by the combined observable is the return type of the closure. In practice, this means you can combine sequences of heterogeneous types. It is the only core operator that permits this
→ Nothing happens until each of the combined observables emits one value. After that, each time one emits a new value, the closure receives the latest value of each of the observable and produces its element.

→ Remember that combineLatest(_:_:resultSelector:) waits for all its observables to emit one element before starting to call your closure. It’s a frequent source of confusion and a good opportunity to use the startWith(_:) operator to provide an initial value for the sequences, which could take time to update.

As shown below There are several variants in the combineLatest family of operators. They take between two and eight observable sequences as parameters. As mentioned above, sequences don’t need to have the same element type.

As shown in Figure 11 another variant of the combineLatest family takes a collection of observables and a combining closure, which receives latest values in an array. Since it’s a collection, all observables carry elements of the same type.

Figure 11

combineLatest completes only when the last of its inner sequences completes. Before that, it keeps sending combined values. If some sequences terminate, it uses the last value emitted to combine with new values from other sequences. As shown in Figure 12 subject1 terminated but it still using it last value

Figure 12

Useful Links

Senior iOS Engineer | HungerStation | Delivery Hero