Reprinted from: http://fengdeng.github.io/blog/2016/01/22/rxswift-dao-di-%5B%3F%5D-ge-uitextfieldshi-ru-he-he-%5B%3F% 5d-ge-uilabelbang-ding-de/
Read more and think it over!
As long as one line of code
writeTextField.rx_text.bindTo(displayLabel.rx_text)
Look at the effect
So how is this going to be achieved?
Overall analysis
代码层:writeTextField的rx_text通过bingTo这个函数和displayLabel的rx_text绑定了。Rx思想:一个被观察者(Observable)通过bingTo函数和一个观察者(Observer)绑定了,这样无论被观察这如何变化,观察者都了如指掌
Deep analytic writetextfield.rx_text
This is a observable. is also a observer. Rx_text is an extended property of Rxswift to Uitextfield, on the code
public var rx_text: ControlProperty<String> { return rx_value(getter: { [weak self] in self?.text ?? "" }, setter: { [weak self] value in self?.text = value })}
Rx_text is a controlproperty<string>
. Generated by the following function. Let's take a look at that function
Func rx_value<t:equatable> (Getter Getter: ()-T, Setter:t-I, Void), controlproperty<t> {Let source:observable<t> = observable.create {[weak self] observer on guard let control = Self else { Observer.on (. Completed) return nopdisposable.instance} observer.on (. Next (Getter ())) Let Controltarget = Controltarget (Control:control, controlevents: [. Alleditingevents,. ValueChanged]) {control in Observer.on (. Next (Getter ()))} return anonymousdisposable {Controltarget.dispose ()}}. Dist Inctuntilchanged (). Takeuntil (rx_deallocated) return controlproperty<t> (Values:source, Valuesink:anyobse RVer {event in Mainscheduler.ensureexecutingonscheduler () switch event {case. Next (let value): Setter (value) case. Error (let error): Bindingerrortointerface (Error) break case. CompleTed:break}})}
This function is Uicontrol, and all Uicontrol subclasses have ha. Uitextfield is a subclass of Uicontrol
The function is a little bit long, we analyze it one step at a time, in fact, two sentences
The first sentence, the source generation process. Source is a observable, which is where the observable
- Get self first, get no direct completed
- Get it, straight next a getter just passed in. Here is
self?.text ?? ""
, that flows away a observable
- Generate a
ControlTarget
, this ControlTarget
whenever ValueChanged
will flow away a observable (this ControlTarget
a bit more, next talk)
- After three steps above, here is a observable. For this observable
distinctUntilChanged()
, this function shows that only a string change will continue to flow down
takeUntil(rx_deallocated)
Until this Uitextfield is released.
- Source ends, this process of source is the 5 steps above
In fact, if a Uitextfield rx_text as a observable, the above code is enough.
In order to implement Uitextfield can also be used as observer, so the following code.
The second sentence, through source, generates one ControlProperty<String>
. The observer is the type to be returned by this function. It is both a observer and a observable
ControlProperty<PropertyType>
the initialization method of a direct call is generated
Look at a closure that the initialization method brings in.
AnyObserver { event in MainScheduler.ensureExecutingOnScheduler() switch event { case .Next(let value): setter(value) case .Error(let error): bindingErrorToInterface(error) break case .Completed: break }
Because UI actions must be in the main thread. MainScheduler.ensureExecutingOnScheduler()
this sentence is to determine if the current thread is
The following code is a response that receives a stream when Uitextfield as a observer.
Displaylabel.rx_text
This is a observer rx_text is an extended property of Rxswift to Uilabel, on the code
public var rx_text: AnyObserver<String> { return AnyObserver { [weak self] event in MainScheduler.ensureExecutingOnScheduler() switch event { case .Next(let value): self?.text = value case .Error(let error): bindingErrorToInterface(error) break case .Completed: break } }}
Very simple, only the code that responds to the stream. If there is a flow,self?.text = value
Some students may have doubts, Uitextfield can be observed, can also be observers. Uilabel can only be the observer, if I want to observe the text of Uilabel What to do???
Haha, easy,please try KVO
displayLabel.rx_observe(String.self, "text").subscribe { (event) -> Void in switch event{ case .Next(let m): print(m) case .Completed: print("") case .Error(let t): print(t) } }
KVO is still relatively simple, we can see for ourselves. Maybe next time I write
BindTo
bingTo
Is the expansion of observable
public func bindTo<O: ObserverType where O.E == E>(observer: O) -> Disposable { return self.subscribe(observer)}
Internally called Observable's subscribe method to associate with a observer
This is the subscribe method that calls the Controlproperty.
public func subscribe<O : ObserverType where O.E == E>(observer: O) -> Disposable { return _values.subscribe(observer)}
_VALUES.SUBSCRIBE (Observer) calls the Subscribe method of the Subscribeon class,
Subscribeon did not implement the Subscribe method, then went to his father class producer to call the
override func subscribe<O : ObserverType where O.E == Element>(observer: O) -> Disposable { if !CurrentThreadScheduler.isScheduleRequired { return run(observer) } else { return CurrentThreadScheduler.instance.schedule(()) { _ in return self.run(observer) } }}
Producer again went to its subclass Subscribeon to call the Run method
override func run<O : ObserverType where O.E == Ob.E>(observer: O) -> Disposable { let sink = SubscribeOnSink(parent: self, observer: observer) sink.disposable = sink.run() return sink}
When each value of Uitextfield is generated, the following method is called, in SubscribeOnSink
this class
func on(event: Event<Element>) { forwardOn(event) if event.isStopEvent { self.dispose() }}
forwardOn(event)
This method also goes to the SubscribeOnSink
parent class of this class to invoke the
final func forwardOn(event: Event<O.E>) { if disposed { return } _observer.on(event)}
Finally transferred to _observer.on(event)
this sentence. is also the method of Uilabel Rx_text, on
on(event)
is a closure, in Uilabel Rx_text equivalent to the following code
{ [weak self] event in MainScheduler.ensureExecutingOnScheduler() switch event { case .Next(let value): self?.text = value case .Error(let error): bindingErrorToInterface(error) break case .Completed: break }
The above is a complex inheritance?? Method call. Read more and think it over!
At this point, a complete observable and a observer binding end
Uitextfield and a Uilabel binding analysis