Why use RxSwift

Swift is a static language. Static languages have an impact on the passing of values, callbacks to responses, communication, and so on. Unlike OC, which has a runtime, messages can be sent dynamically. So you need RXSwift to make up for the static language.

2. The idea of RxSwift is functional responsive programming, which is in line with the design idea that Swift function is a first-class citizen, and is also the direction of Swift development in the future.

3. RxSwift is a member of the ReactiveX family. Once you know RxSwift, you can expand to other frameworks in the ReactiveX family.

Functional responsive programming

1. Functional expressions

The function comes from mathematics and is expressed as y = f(x), where y is the dependent variable and x is the independent variable. Y will change as x changes.

In Swift, x is a parameter, f is a function, and y is the result of the function — the return value.

In certain cases, x can be expressed as x = f(x), then the above formula can be deformed to y = f(f(x)). That is, one function can take arguments to another function. Increased function flexibility. This is the core idea of functional programming.

2. Functional response

For example:

var a: Int = 10        
var b: Int = a + 10 
Copy the code

If the value of B in the above code needs to always change with the value of A, how do we do this? We need to listen for changes in a, and B changes in response to changes in A. This is the KVO mechanism in OC.

Unfortunately, however, there is no KVO key-value listening in Swift. Therefore, we need RxSwift to achieve more advanced and convenient functional responsive programming.

Experience the charm of RxSwift

  • KVO listens for the Name property in Person
self.person.rx.observeWeakly(String.self."name")
    .subscribe(onNext:{(value) in
        print(value as Any)
    })
    .disposed(by: disposeBag)
Copy the code
  • Listen for button click events
self.button.rx.tap
    .subscribe(onNext: {(value) in 
        print("Click the button.")
    })
    .disposed(by: disposeBag)
Copy the code
  • Listen for input to the input box
self.textFiled.rx.text.orEmpty
    .subscribe(onNext: {(text) in
	print(text)
    })
    .disposed(by: disposeBag)
Copy the code
  • UITextFiled Input binds UILabel
self.textFiled.rx.text
		.bind(to: self.button.rx.title())
		.disposed(by: disposeBag)
Copy the code
  • Gestures to monitor
let tap = UITapGestureRecognizer(a)self.label.addGestureRecognizer(tap)
self.label.isUserInteractionEnable = true
tap.rx.event.subscribe(onNext: {(tap) in
		print(tap.view)
})
.disposed(by: disposeBag)
Copy the code
  • Listen to inform
NotificationCenter.default.rx.notifcation(UIResponder.keyboardWillShowNotification)
.subscribe(onNext: {(noti) in
		print(noti)
})
.disposed(by: disposeBag)
Copy the code
  • The timer
timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)

timer.subscribe(onNext: {(num) in
    print(num)
})
.disposed(by: disposeBag)
Copy the code

RxSwift core principle analysis

RxSwift uses three steps

Step 1: Create the sequence

let ob = Observable<String>.create { (observer) -> Disposable in
            
    return Disposables.create()
}
Copy the code

Step 2: Subscribe signal

let _ = ob.subscribe(onNext: { (text) in
    print("Subscription information:\(text)")
}, onError: { (error) in
    print("error: \(error)")
}, onCompleted: {
    print("End of subscription") {})print("Destroyed")}Copy the code

Step 3: Send a signal

let ob = Observable<String>.create { (observer) -> Disposable in
            
    // Step 3: Send a signal
    observer.onNext("Information 1")
            
    return Disposables.create()
}
Copy the code

RxSwift source code analysis

  • First analyze the first step to create the sequence. Create Observable sequences using the Create method of Observable.

View RxSwift source code

So if we look up at the comments, we’ll seea “seealso,” which translates to “see you.” Well, it seems to mean you need to look at other documents. And it’s followed by a link, so are we going to look at the document?

Reactivex. IO /documentati… “, pointing to the HTML of a create file, we wonder if there is a create file in the source code, let’s search for it in the project

The return value is AnonymousObservable(SUBSCRIBE). An internally anonymous observable sequence class. The argument SUBSCRIBE creates the closure in the sequence as the first step.

Also, at the bottom of the file you can find an implementation of the AnonymousObservable anonymous internal observable sequence class

  • Step 2: Subscribe signal Uses the Subscribe signal of ObservableType.

To find the source code

Does this sound strange to you? The first step has an observable sequence, and the second step has an observer, but there seems to be no connection between them. How to subscribe? And how is the signaling of the third step performed?

We looked for it, but it seemed only possible

self.asObservable().subscribe(observer)
Copy the code

Let’s take a look at asObservable() and check it out. Subscribe (Observer) subscribe(Observer) Well, let’s go ahead and say self, self we know is the observable sequence that we created in the first step

asObservable()
subscribe
asObservable()

Let’s look at the subscribe method. The rxAbstractMethod() method is called internally. But after checking, this method is not implemented. The analysis stops at this point. Recall that the Observable object is created by the create method. And inside it is an instance object that initializes an internally anonymous observable sequence. Let’s go back to the Create file and look at the source code. And we find that there’s no subscribe function.

The AnonymousObservable class inherits from Producer, so subscribe is the same method as its parent Producer.

By looking at the source code

Producer
subscribe
self.run(observer, cancel: disposer)

Find the run function below. Find that there is only one rxAbstractMethod() function call inside. The actual run function is not implemented. In fact, this is a design pattern. Curious babies can learn about it by themselves. I’m not going to expand the narrative here. The run function, which we’ve already seen, is a subclass of the Producer object AnonymousObservable, an AnonymousObservable sequence

In this method, you pass in the AnonymousObserver AnonymousObserver instance object that you created earlier. An AnonymousObservableSink instance object is created and its run() function is called. Let’s look at the implementation of the run() function. Parent._subscribehandler (AnyObserver(self)) is called. Parent is an instance of AnonymousObservable. That is, AnonymousObservable._subscribeHandler(AnyObserver(self)) is called.

We already know from analyzing the first step of creating the observable sequence that the _subscribeHandler holds is the closure passed in in the first step of creating the observable sequence. This closure is now executed by calling _subscribeHandler. And the method in the closure is the third step to send a signal.

After the above source code analysis, we have seen the data flow from creating observable sequences > subscribing signals > sending signals.

  • The third step is to send a signal callobserver.onNext()The function sends signals.

As analyzed earlier, an internal anonymous observer is created in the second step of subscribing to the signal. How is this observer passed into the closure that created the sequence in the first step? Let’s analyze it.

As we know, in the return that calls SUBSCRIBE in the second step, we call the Subscribe function of the Producer object and pass observer as an argument. When we call the run function of the AnonymousObservable sequence class AnonymousObservable in the subscribe function, we pass an observer to the run function.

In the AnonymousObservable. Run function, an Observer is passed to the AnonymousObservableSink instance object when an instance of AnonymousObservableSink is initialized. When run is called, an AnyObserver instance is created using the AnonymousObservableSink instance object, which is passed to the closure of the creation sequence, resulting in an Observer Observer.

The onNext callback in the second step subscription signal closure is invoked by calling the onNext() function of the Observer object. To send the delivered subscription information.

After the above analysis process, RxSwift source code has been analyzed. The core principle of RxSwift is also understood clearly. However, the design mode used in RxSwift has already programmed the idea is that we need to continue to learn and master in the future use.

Finally, attached to RxSwift a source analysis mind map, I hope to help you.