The original address: www.jianshu.com/p/0e0703466…
As one of the ReactiveX family of RxSwift on Github as of now Star:16K. Why is this framework so popular, and how is the underlying implementation implemented as the poster child for functional responsive frameworks? This article is fully declassified
RxSwift core process
RxSwift this excellent framework, the design of the API is very simplified, so that unfamiliar users can also be very fast
- 1: Create a sequence
- 2: Subscription sequence
- 3: sends signals
Observable<String>. Create {(obserber) -> Disposablein// 3: send signal obserber.onnext ("Cooci - Frame Class")
return// 2: Subscribe}. Subscribe (onNext: {(text)in
print("Subscribe to :\(text)")}) // Console prints: "Subscribe to :Cooci - frame class"Copy the code
When I first started exploring, I was curious as to why the string in our Cooci-frame class was printed in the closure of the subscribe sequence. Here is my code analysis
Analysis code:
- 1: code to create the sequence
Create
At the back of theThe closure of A
There is a3: sends signals
If it is to be executedSend a signal
I have to come to thisThe closure of A
- 2: We execute
2: Subscription sequence
To create theClosure B
- 3: We clearly know from the results, execute first
The closure of A
把Cooci - Frame class
Passed on toClosure B
- Guess: there is a nested closure execution call inside the code! Guess the truth, we began to read the source code to verify
PS: To tell the truth, the source code of RxSwift framework is really more complex and a lot of, a lot of foundation is weak or impatient partners are easy to give up. But if you read this blog post, you’re in luck: I’ll give you a quick and brief introduction, with my mind map at the end!
RxSwift core logic
Create a sequence
extension ObservableType {
// MARK: create
public static func create(_ subscribe: @escaping (AnyObserver<E>) -> Disposable) -> Observable<E> {
return AnonymousObservable(subscribe)
}
}
Copy the code
You can clearly see that our observable sequence is created using the protocol extension create method, which creates an AnonymousObservable (AnonymousObservable sequence) named after the author: This class is an inner class with some common features (classes with their own functionality are named) and I post the inheritance of this class below
From the figure above, we can clearly see the inheritance relationship. So with so much content and so many layers of nesting, here’s what we need to know:
create
Method to create an internal objectAnonymousObservable
AnonymousObservable
The external closure is savedAnonymousObservable
inheritedProducer
It has a very important methodsubscribe
Subscribe to the sequence
Subscribe is not the same method as subscribe
From theObservableType
Extended function of
extension ObservableType { public func subscribe(onNext: ((E) -> Void)? = nil, ...) -> Disposable {// because length omission does not affect the code we are exploringlet observer = AnonymousObserver<E> { event in
switch event {
case .next(letvalue): onNext? (value)case .error(let error):
if let onError = onError {
onError(error)
}
else {
Hooks.defaultErrorHandler(callStack, error)
}
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
}
}
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
}
}
Copy the code
Code description:
E
The idea here is thatSwift
If you take a close look at the source code of the inheritance chain of the observable sequence, it should not be difficult to conclude: thisE
That’s our sequence type, which we have hereString
public class Observable<Element> : ObservableType {
/// Type of elements in sequence.
public typealias E = Element
Copy the code
- Created a
AnonymousObserver (anonymous internal Observer)
Techniques and oursAnonymousObservable
Pretty much, its initialization here is the closure parameter that holds the outsideonNext, onError , onCompleted , onDisposed
Handles the call to the callback closure, which I’ll post for you belowThe observer
To help you understand
self.asObservable()
This is oursRxSwift
Just to keep it consistentself.asObservable().subscribe(observer)
The essence is thatself.subscribe(observer)
Through the inheritance relationship of observable sequence, we can locate very quicklyProducer
The subscription code
override func subscribe(_ observer: O) -> Disposable where O.E == Element {
if! CurrentThreadScheduler. IsScheduleRequired {/ / space reasons, we omit some code, convenient we understand...return disposer
}
else {
return CurrentThreadScheduler.instance.schedule(()) { _ in
let disposer = SinkDisposer()
letSinkAndSubscription = self.run(observer, cancel: Disposer) //return disposer
}
}
}
Copy the code
- The destruction code and scheduler code are not analyzed here
self.run
This code is ultimately produced by usProducer
This extends to our specific transaction codeAnonymousObservable.run
override func run (...) {
let sink = AnonymousObservableSink(observer: observer, cancel: cancel)
let subscription = sink.run(self)
return (sink: sink, subscription: subscription)
}
Copy the code
sink.run
The writing method is also better, business processing or sink, so that the division of labor is more clear
func run(_ parent: Parent) -> Disposable {
return parent._subscribeHandler(AnyObserver(self))
}
Copy the code
parent
It was sent from aboveAnonymousObservable
object- We are very excited to see
AnonymousObservable._subscribeHandler
From this code we are puzzled why ourSequence of subscription
The process will execute usSequence of closure
“And then executeSend a response
- The code to send the response will be examined later, but there is one more important guy
AnyObserver(self)
public init<O : ObserverType>(_ observer: O) where O.E == Element {
self.observer = observer.on
}
Copy the code
- In this constructor, we create a structure
AnyObserver
A message is savedAnonymousObservableSink. On function
, notAnonymousObservableSink
It’s a place where most first-time visitors make mistakes. I don’t know if you realize this!
Send a response
Our analysis from above is very clear:Obserber.onnext ("Cooci - Frame class ")
The essence of:Anyobserver. onNext("Cooci - Frame class ")
At this time, we found that AnyObserver does not have this method, which is normal! General idea, find the parent class, find the protocol
extension ObserverType {
public func onNext(_ element: E) {
self.on(.next(element))
}
}
Copy the code
- The outside world
Obserber.onnext ("Cooci - Frame class ")
Deform again:Anyobserver.on (.next("Cooci - frame class ")) anyobserver.on (.next("Cooci - frame class "))
You have to focus on thisAnyObserver
Call theon
The message inside is.next function
..next function
With our final parameters
public struct AnyObserver<Element> : ObserverType {
public init<O : ObserverType>(_ observer: O) where O.E == Element {
self.observer = observer.on
}
public func on(_ event: Event<Element>) {
return self.observer(event)
}
}
Copy the code
self.observer
Constructor initialization is:AnonymousObservableSink. On function
- See here to transform again:
self.observer(event)
->AnonymousObservableSink .on(event)
Among themEvent =.next("Cooci - Frame class ")
Eventually our core logic comes backsink
This amazing tube, it’s amazing to see this,RxSwift
This design ability, who else
class AnonymousObservableSink<O: ObserverType>: Sink<O>, ObserverType {
func on(_ event: Event<E>) {
switch event {
case .next:
if load(self._isStopped) == 1 {
return
}
self.forwardOn(event)
case .error, .completed:
if fetchOr(self._isStopped, 1) == 0 {
self.forwardOn(event)
self.dispose()
}
}
}
}
Copy the code
self.forwardOn(event)
This is also the core code to execute becauseAnonymousObservableSink
inheritanceSink
There is also encapsulation, as shown in the code below
class Sink<O : ObserverType> : Disposable {
final func forwardOn(_ event: Event<O.E>) {
if isFlagSet(self._disposed, 1) {
return
}
self._observer.on(event)
}
}
Copy the code
- Among them
self._observer
That’s what we initialized to saveObserver: AnonymousObserver
- So we transform it to get the essence:
Anonymousobserver.on (.next("Cooci - frame class "))
Oh my god! Here logic comes back to usSubscribe to the sequence
Created whenAnonymousObserver
A call to the parameter closure of! Everything feels so wordy, but it’s so resourceful.
let observer = AnonymousObserver<E> { event in
switch event {
case .next(letvalue): onNext? (value)case .error(let error):
if let onError = onError {
onError(error)
}
else {
Hooks.defaultErrorHandler(callStack, error)
}
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
}
}
Copy the code
- judge
event
And then callonNext? (value)
Because the associated values of enumerations (Swift
Very powerful function)Value = "Cooci - frame class"
And then there’s the outside worldCall to the onNext closure
, so this time source code parsing here, I believe you have fully masteredRxSwift
Finally, here is attached our analysis diagram
Summary: RxSwift structure
- 1: Is the sequence of feelings all over the world sequence – unified coding, anytime, anywhere to enjoy
- 2: Sink a list of requirements through functional thinking (encapsulating what developers don’t care about) – optimize code and save logic
- 3:
RxSwift
The most typical feature is resolutionSwift
The response capability of this static language, using the time dimension series changes as the axis, the user subscription care can be kept alive along with the axis, reach the subscription once, the response has been continued ~
For RxSwift, you have a better understanding. If you want to have a better discussion, you can enter the iOS technology group to discuss and communicate with them
- Click to join the iOS developer group for discussion