2 hours to master RxSwift — Part 2: Core concepts

Needone App
4 min readMar 14, 2023

--

In the example of previous article: 2 hours to master RxSwift — Part 1, we probably saw some code such as subscribe without any explanation, we will go through some key concepts and principles on the RxSwift.

Observable

Observable is core concept in RxSwift. In RxSwift, an Observable is a sequence that emits events (values or errors) over time, and notifies its observers(also called Subscribers) when these events occur.

In RxSwift world, arrays, strings, numbers, timers, network requests, and user interface events needed to convert into Observables first before use. An observable can emit a number of events followed by either a completion event (signifying that the sequence has ended) or an error event (signifying that an error occurred).

Subscriber

On the other hand, when events is emitted from Observable, we need the Subscriber to receive, which specify who can and will receive those events. This process is callled subscrition. A similar example in the real world is when we follow a youtuber, we will receive notification once they updated their channel.

The Subscriber has three main methods to deal with events:

  1. onNext: this is the main one used to handle every emitted element from the Observable.
  2. onError: handles any errors emitted by the Observable, such as network failure, fallbacks and so on.
  3. onCompleted: handles the completion event emitted by the Observable. Once reevied the completion event, the Observable will NO emit any event anymore.

The Subscriber also has a dispose() method that can be used to cancel the subscription and stop receiving events from the Observable.

Example of Observable and Subscriber

The following is an example of creating an Observable and Subscriber

import RxSwift

// Create an observable that emits an integer array
let observable = Observable.Observable.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

// Subscribe to the observable to receive its emitted values
_ = observable.subscribe(onNext: { value in
print(value)
}, onCompleted: {
print("Observable completed")
})

We will get:

1
2
3
4
5
6
7
8
9
10
Observable completed

With the example above, first create an Observable emits three integer values. Then subscribe to the Observable and print each emitted value to the console using the onNext closure. Finally, we print "Observable completed" when the Observable completes emitting values.

Operator

In RxSwift, operators are functions that can “operate” on Observables and return Observables, which will allow us to do some specific task in a simple way. Take the above example, suppose we only want even number, we can simply add a filter:

let observable = Observable.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

// Subscribe to the observable to receive its emitted values
_ = observable
.filter { $0 % 2 == 0 } // filter to even numbers
.subscribe(onNext: { value in
print(value)
}, onCompleted: {
print("Observable completed")
})

We will get the output:

2
4
6
8
10
Observable completed

Beside filter, there are many operators in RxSwift, each with its own specific functionality, here are some common used ones:

  • map: transforms each element emitted by an Observable by applying a function to it.
  • filter: filters the elements emitted by an Observable based on a predicate.
  • flatMap: transforms each element emitted by an Observable into another Observable, then flattens the emissions from these Observables into a single stream.
  • merge: combines multiple Observables into a single Observable by merging their emissions.
  • zip: combines the emissions of multiple Observables into a single Observable by emitting tuples of corresponding elements.

We will cover more on this in the later article.

Subjects

In RxSwift, the subject is a special type which is a combine of observable and subscriber, meaning it can either observed by multiple subscribers, and also can emit events to others.

There are several types of subjects available in RxSwift, including:

  1. PublishSubject: doesn’t have an init value, emits only new value to its subscribers
  2. BehaviorSubject: have an init value, emits latest value to subscribers
  3. ReplaySubject: emits a buffer of values to new subscribers, so they can receive max buffer size past values before subscription
  4. AsyncSubject: emits only the final value to its subscribers only after the sequence has completed
// Example of PublishSubject
let subject = PublishSubject<String>()
subject.onNext("test") // No one is listening at this point
let subscription = subject.subscribe(onNext: { string in
print(string)
})
subject.onNext("abc") // test is not printed, only abc


// Example of BehaviorSubject
let subject = BehaviorSubject(value: "abc")
subject.onNext("def") // print out due to this is the latest value
let subscription = subject.subscribe(onNext: { string in
print(string)
})
subject.onNext("ghi") // print out def and ghi


// Example of ReplaySubject
let subject = ReplaySubject<String>.create(bufferSize: 4)
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onNext("4")
subject.onNext("5")
let subscription = subject.subscribe(onNext: { string in
print(string)
})
subject.onNext("6")
subject.onNext("7")
subject.onNext("8")


// Example of AsyncSubject
let subject = AsyncSubject<String>()
subject.onNext("Hello")
subject.onNext("World")
let subscriptionOne = subject.subscribe(onNext: { string in
print(string)
})
subject.onNext("!")
subject.onCompleted() // print out ! if onCompleted is called, otherwise no output.

What is Next

In the next article we will have a look at the Observable in depth.

👉 If you want received more stories like this, please subscribe my channel to get the latest update in time

Originally published at https://needone.app on March 14, 2023.

--

--