As a beginner of RxSwift, it is very scary to write this article, but I will explain a code in the official Demo of RxSwift in detail, so that those who have not been exposed to RxSwift can feel why RxSwift makes our development easier and more efficient.

What exactly is RxSwift?

RxSwift is a type of functional responsive programming. What is functional programming? The most important concept of functional programming, as some of you will be happy to know, is immutable. Anyway, what is immutable? I read a lot of articles, but I was completely confused by their professional descriptions. Let me tell you my opinion: Friends with rich debug experience know a fact that 80% of bugs in programs can be found by tracking variable values. Why? Conversely, the biggest cause of bugs is value changes. It is surely a bold thought that if there is a way to eliminate state changes (why not say value, because Rx is not only immutable for values, but also for events, and therefore is accurately described as “state”), So there are no bugs? Functional programming was born for this purpose.

How is it that functional programming is immutable? The answer is “sequence”. Since I cannot change the state, when I need to change it, I will generate a new state. After several changes, I will generate several states, and “sequence” is a container for these states (you can view it as an array). Does the change in state cease to exist? The answer is yes, I just need to make commands to the states in the sequence separately, and they will not affect each other, so the probability of bugs will be greatly reduced.

So now that you have a sequence, how do you generate a sequence, how do you combine multiple sequences, and how do you deal with each element in each sequence? There are so many operators in RxSwift to solve these problems, which is one of the reasons RxSwift is so hard to learn. But we just need to understand that the ultimate goal of these operators is to make “sequences” what we want them to be. You’ll get twice the result with half the effort.

To move on to reactive programming, let’s look at some code:

 var a: Int = 0
 var b: Int = 0
 var c = a + b
 a = 1
 print(c)
Copy the code

Despite a assignment before c printing is 1, but at the time of assignment to c a + b is equal to zero, the latest results, we want to make c requires before c assignment will be to change the value of a 1, so if the value of a and b in the following code will continue to change, just need to constantly write a line to assign a value to c code: C = a + b, this is too much trouble, responsive was born in order to solve this problem, when there is a change when a or b, c value will respond to changes in value of a or b, so called reactive, how responsive to achieve this, the most simple and easy to understand way is through the attribute listeners a or b, When either a or B changes, c is reassigned. In fact, no matter how to write code, is nothing but the implicit c = a + b this one line of code, even if we go directly to the operating pointer, also needs to have one line of code that will be two Pointers point to the value of the additive, so the response is not difficult to understand the technology, but reactive programming can greatly improve the readability of the code, a more intuitive and easier to maintain.

RxSwift is a combination of functional, responsive, and chained programming that makes it easier to write business code, even if you can’t use it on a project for any reason.

A few more words here: There are many blogs that refer to “sequence” as “flow, signal, pipeline” and so on, which is helpful to understand RxSwift, but the project maintainer of RxSwift clearly doesn’t see it that way. Here’s an InfoQ interview with Project maintainer Krunoslav Zaher:

Thinking about observable sequences in different, less precise ways can cause problems (flows, signals, conduits, etc.). Those things can sometimes be used to help newcomers explore Rx, but if used for too long, they can only cause a lot of confusion later in the development. People sometimes use them because Rx can be used to simulate the multistate part of a system, but that’s only part of the story, and I recommend you don’t think about it that way.

The problem with thinking about those terms (flows, signals, conduits, etc.) is that they carry an implicit assumption:

Observables are defined with shared values, and the current values can be set externally. Observables, on the other hand, get cancelled out of nowhere, which looks like futures or promises.

And in fact:

Observable is just a definition of how to evaluate a sequence. After no calculation is defined in sequence (let the result = source. The map (transformObservableSequence) automatically performed. This is the same as SequenceSequence in Swift. Calculations are performed when an observer is bound (which is the same as calling generate in SequenceType), and specific calculations can be cancelled by processing the results of the Disposable object. Observables can certainly represent multistate computations that share underlying bindings and source Observable sequences (using shareReplay(1) operations, etc.), but this is not the default behavior.

I think part of the problem is that maybe people have been using Future, Promise, or some other simpler, similarly used library, so they naturally assume that Rx behaves the same way in other situations, which is obviously confusing for newcomers.

Oddly enough, the one-sided nature of Rx can be a problem for people who are just starting to use it. Sometimes the bar gets so high that people become unmotivated, but on the other hand, that’s why I personally find Rx beautiful.

The beauty of it is that you can teach someone to use Rx in just one sentence: An Observable represents an Observable sequence of element type T (like SequenceSequence in Swift), Each element can register its own observer (return signal) that receives sequence elements by calling the subscribe method (the same as generate in SequenceSequence).

If this aspect is clear, everything else is just detail, or becomes very obvious and natural. Thinking of Rx as another library rather than a different concept/abstraction, and starting to look it up on Stack Overflow or similar sites, will cause a lot of problems. In learning Rx, the only part to learn is to understand the sentences of observable sequences, so that everything else is obvious. That’s when the steep learning curve disappears.

RxSwift official demo parsing

The following is a small module that implements Github’s registration function. Let’s take a look at the directory structure (the files that are not marked green are RxSwift’s more streamlined implementation for THE UI, so we won’t discuss them here) :

Obviously, this is a standard MVVM architecture. In my opinion, RxSwift is the perfect CP for MVVM. RxSwift is very suitable for solving the problem of ViewModel State and View binding in MVVM. As an aside, the demo uses the idea of protocol-oriented programming, which is also worth referring to, and can greatly improve the reuse rate and decoupling of code. I recommend you to search for li Jiexin’s speech at swift Developer Conference 2016 on MOOCs. I will not attach the address here.

Moving on to the efficacy:Under normal circumstances, we need to listen for changes in the text property in the proxy method of textField, and then use a judgment similar to this structure:

if  validPassWord(textfield.text) {
      tipLabel1.text = .
      tipLabel.textColor = .
} else {
      code
}

if textfield1.text = = textfield2.text {
      tipLabel2.text = .
      tipLabel2.textColor = .
}else {
      code
}
Copy the code

In fact, the reality is much more complicated than my pseudo-code, as you all know. So how does RxSwift do this? Let’s take a look at the code in viewController (I’ll add a comment to make it easier to understand) :

override func viewDidLoad(a) {
        super.viewDidLoad()
        // Here is the constructor of the viewModel. The constructor takes the "sequence" generated by the text of the three Textfields.
        // Whenever textField.text is changed, a new Element is generated in the "sequence"
        let viewModel = GithubSignupViewModel1(
            input: (
                . / /. Rx. Text. OrEmpty asObservable () is to provide the UIKit RxSwift extensions, can quickly generate a sequence of observed the following in the same way
                username: usernameOutlet.rx.text.orEmpty.asObservable(),
                password: passwordOutlet.rx.text.orEmpty.asObservable(),
                repeatedPassword: repeatedPasswordOutlet.rx.text.orEmpty.asObservable(),
                loginTaps: signupOutlet.rx.tap.asObservable()
            ),
            dependency: (
                // Network interface
                API: GitHubDefaultAPI.sharedAPI,
                // A utility class to verify that the input is valid
                validationService: GitHubDefaultValidationService.sharedValidationService,
                // Popup window, click the login button prompt message
                wireframe: DefaultWireframe.shared
            )
        )

        // The viewModel constructor processes three "sequences" in and out, and generates the following five observable "sequences"
        // let validatedUsername: Observable
      
        // Check whether the username is available
      
        // let validatedPassword: Observable
      
        // Check whether the password is available
      
        / / let validatedPasswordRepeated: observables < ValidationResult > / / repeat password is available
        // let signupEnabled: Observable
      
        // Register button can be clicked
      
        Observable
      
        // Let signedIn: Observable
       
      
        Observable
      
        Observable Observable
       
      
       // ValidationResult is an enumeration
       enum ValidationResult {
            case ok(message: String)
            case empty
            case validating
            case failed(message: String)}// With these sequences, you can bind data and controls in the controller
        viewModel.signupEnabled
            // Subscribe to an event handler closure for an observable sequence. Whenever a new element is added to the sequence, the method automatically signals and executes the code in the closure and returns a type that complies with Disposable, which is equivalent to garbage collection and destroys the sequence.
            .subscribe(onNext: { [weak self] valid  in
                self?.signupOutlet.isEnabled = valid
                self?.signupOutlet.alpha = valid ? 1.0 : 0.5
            })
            .disposed(by: disposeBag)

        viewModel.validatedUsername
            /** Bind is the same thing as subscribe, but it's a better way to react to the relationship between an observable and an observer. From the point of view of a code reader, you might need to find out who the observer is in the event sequence, but with bind, You can intuitively see who the observer is, which is like a layer of subscribe again, let the observer to complete things in their own code area, no longer need to write in the controller, code really called a smooth, there is a feeling of a clear. It also lets you de-couple your code without realizing it. * /
            .bind(to: usernameValidationOutlet.rx.validationResult)
            .disposed(by: disposeBag)

        viewModel.validatedPassword
            .bind(to: passwordValidationOutlet.rx.validationResult)
            .disposed(by: disposeBag)

        viewModel.validatedPasswordRepeated
            .bind(to: repeatedPasswordValidationOutlet.rx.validationResult)
            .disposed(by: disposeBag)

        viewModel.signingIn
            .bind(to: signingUpOulet.rx.isAnimating)
            .disposed(by: disposeBag)

        viewModel.signedIn
            .subscribe(onNext: { signedIn in
                print("User signed in \(signedIn)")
            })
            .disposed(by: disposeBag)
        / /}

        let tapBackground = UITapGestureRecognizer()
        tapBackground.rx.event
            .subscribe(onNext: { [weak self] _ in
                self?.view.endEditing(true)
            })
            .disposed(by: disposeBag)
        view.addGestureRecognizer(tapBackground)
    }
Copy the code

#### summary originally wanted to deconstruct the code deconstruction in the official demo in detail, which is really very good and concise code, and then talk about the meaning of each operator, but this is not my original intention to write this article, I just want to let the friends who have not started to contact RxSwift feel the charm of RxSwift. If you’re interested in RxSwift for the first time in this article, make sure to check it out: RxSwift brings native Reactive programming to Swift. It’s time to learn about RxSwift

Readers would be grateful if they could point out any errors in this article.