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. I’m sure you all have a bold idea that if there was a way to eliminate state changes (why not “value” here, because Rx is not just “stateless” of values

Immutable is also a way to describe events immutably by saying they are not mutable. 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

Even though a is assigned 1 before C prints, a + b is still equal to 0 when C is assigned,

If we want c to get the latest result, we need to change a to 1 before c is assigned,

So if the values of A and B keep changing throughout the rest of the code,

I need to write a line of reassignment code to c over and over again: c = a+ b, which is really cumbersome,

The reactive form was created to solve this problem, when a or B changes,

The value of C changes in response to the value of A or b, so it’s called the reactive formula, so how do you implement the reactive formula,

The easiest way to understand this is through the property listener of a or B, and when you listen for changes in a or B,

I’m going to reassign c. In fact, no matter how you write this code, it’s just implicit c = a + b,

Even if we were to manipulate the pointer directly, we would need a line of code to add the values that the two Pointers point to,

So reactive programming is not a difficult technique to understand, but reactive programming can greatly improve the readability of code,

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 you can cancel specific calculations by processing the result 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).

RxSwift: Github: Github: Github: Github: Github: Github: Github: Github: Github: Github: Github: Github: Github: Github: Github: Github

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() {super.viewdidLoad (); The constructor accepts the "sequence" generated by the text of the three Textfields // whenever textField.text changes, Let viewModel = GithubSignupViewModel1(input: (/ /. Rx. Text. OrEmpty. AsObservable () is to provide the UIKit RxSwift an extension of the observed sequence can quickly generate a, following the same 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, / / validation of the input is legal tools validationService: GitHubDefaultValidationService sharedValidationService, / / popup window, click the login button after the prompt information wireframes: Defaultwireframe.shared)) // The viewModel constructor handles three "sequences" in and out, and generates the following five observable "sequences" // let validatedUsername: Observable<ValidationResult> // User name available // let validatedPassword: Observables < ValidationResult > / / / / password will be available to let validatedPasswordRepeated: Observable<ValidationResult> // Let signupEnabled: Observable<Bool> // let signedIn: Observable<Bool> // Register (control popup) // let signingIn: Observable<Bool> // Is in the register process (control the rotation of the daisies) // ValidationResult is an enumeration. String) case empty case validating case failed(message: Viewmodel.signupenabled // Subscribing to an event closure for an observable sequence. Whenever a new element is added to the sequence, this method automatically signals and executes the code in the closure. And returns a type that complies with Disposable, which is garbage collection, which destroys the sequence. .subscribe(onNext: { [weak self] valid in self? .signupOutlet.isEnabled = valid self? .signupOutlet.alpha = valid ? Prompt (by: DisposeBag) viewModel. ValidatedUsername / * * is equivalent to a bind with the subscribe actually only he can better the relationship between the reaction can be observed sequence and observer Standing in a code reader's point of view, use the subscribe method to subscribe to, You might need to find out who the observer is in the event handler sequence, but with bind, you can see exactly who the observer is, which is essentially a layer of subscribe that allows the observer to do things in its own code area, so that it doesn't have to be written in the controller, and the code reads really smoothly. There is a sense of clarity. 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

conclusion

I wanted to deconstruct the code in the official demo in detail,

It is really very good and concise code, and then to say the meaning of each operator, I want to let the friends who have not started to contact RxSwift feel the charm of RxSwift a little bit.

Competing in the tough iOS market, without mastering and understanding some advantageous technical knowledge, how to compete with others, and how to conquer your interviewer. Those who have done it for three or five years are not necessarily involved in the technical knowledge inside. Maybe what you lack is a summary and a list of interview questions to practice on.

Interview answers and iOS technology resources. I hope I can help you improve your technology!

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.

Follow the hashtags below to find more similar articles