All things are sequences

As mentioned earlier, an Observable can be used to describe a sequence in which elements are generated asynchronously. So many things in our life can be represented by it, for example:

  • Observable<Double>The temperature

    You can think of temperature as a sequence, and then monitor that temperature, and then respond to that temperature. For example, turn on the air conditioner when the room temperature is higher than 33 degrees Celsius.

  • Observable<OnePieceEpisode>One Piece animation

    You can also think of one Piece’s anime as a sequence. Then when an episode of One Piece is updated, we immediately watch that episode.

  • Observable<JSON> JSON

    You can think of the returned JSON of the network request as a sequence. Then, when you get the JSON, print it out.

  • Observable<Void>Task callback

    You can think of a task callback as a sequence. When the task is complete, the system prompts the user that the task is complete.

How to create a sequence

Now we can think of many things in life as a sequence. So how do we create these sequences?

In fact, the framework already helps us create many common sequences. For example: button click, textField current text, switch on/off state, slider current value, etc.

In addition, there are some custom sequences that we need to create ourselves. Here is the most basic way to create a sequence. For example, we create a sequence [0, 1… 8, 9] :

let numbers: Observable<Int> = Observable.create { observer -> Disposable in observer.onNext(0) observer.onNext(1) observer.onNext(2)  observer.onNext(3) observer.onNext(4) observer.onNext(5) observer.onNext(6) observer.onNext(7) observer.onNext(8) observer.onNext(9) observer.onCompleted() return Disposables.create() }Copy the code

The most straightforward way to create a sequence is to call Observable.create and describe the element generation process in the constructor. Observer.onnext (0) generates an element with a value of 0. Then there are nine more elements: 1, 2… 8 and 9. Finally, use observer.oncompleted () to indicate that all elements have been generated and that there are no more.

You can encapsulate functional components in this way, for example, closure callbacks:

typealias JSON = Any

let json: Observable<JSON> = Observable.create { (observer) -> Disposable in

    let task = URLSession.shared.dataTask(with: ...) { data, _, error in

        guard error == nil else {
            observer.onError(error!)
            return
        }

        guard let data = data,
            let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
            else {
            observer.onError(DataError.cantParseJSON)
            return
        }

        observer.onNext(jsonObject)
        observer.onCompleted()
    }

    task.resume()

    return Disposables.create { task.cancel() }
}

Copy the code

In the closure callback, observer.onerror (error!) is called if the task fails. . Observer.onnext (jsonObject) is called if the target element is retrieved. Since our sequence has only one element, we call observer.oncompleted () directly to indicate the end of the task after we successfully get the element. Finally Disposables. Create {task.cancel()} indicates that the network request will be cancelled if the data binding is cleared (the subscription has been cancelled).

So we’ve swapped the traditional closure callback for a sequence. We can then respond to the result of this request with the subscribe method:

Json. Subscribe (onNext: {json in print(" json success: \(json)")}, onError: {error in print(" json failed error: \ [error. LocalizedDescription) ")}, onCompleted: {print (" json mission success completion ")}) disposed (by: disposeBag)Copy the code

We subscribe to onNext,onError, and onCompleted in response to the onNext,onError, and onCompleted events in our constructor function when we create json. We call these events events:

The Event – events

public enum Event<Element> {
    case next(Element)
    case error(Swift.Error)
    case completed
}

Copy the code
  • Next – The sequence produces a new element
  • Error – An error occurred while creating the sequence, causing the sequence to terminate
  • Completed – All elements of the sequence have been successfully generated and the entire sequence is complete

You can use these events wisely to implement business logic.

The decision tree

Now we know how to create sequences in the most basic way. You can also choose other ways to create sequences by studying decision trees.

Characteristics of the sequence

We all know that Swift is a strongly typed language, and one advantage strongly typed languages have over weakly typed languages is that they are more rigorous. We can tell by type what the characteristics of an instance are. Likewise, there are some feature sequences in RxSwift Observable, which can help us describe the sequence more accurately. They also give us syntactic sugar so we can write code in a more elegant way:

  • Single
  • Completable
  • Maybe
  • Driver
  • Signal
  • ControlEvent

*ℹ️ Tip: Since the name of ** Observable * is too long, it makes reading difficult in many cases, so the author will abbreviate it as “sequence” when necessary.