Uitextfield and a Uilabel binding analysis

Source: Internet
Author: User
Tags uicontrol

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

    1. Get self first, get no direct completed
    2. Get it, straight next a getter just passed in. Here is self?.text ?? "" , that flows away a observable
    3. Generate a ControlTarget , this ControlTarget whenever ValueChanged will flow away a observable (this ControlTarget a bit more, next talk)
    4. 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
    5. takeUntil(rx_deallocated)Until this Uitextfield is released.
    6. 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

    1. ControlProperty<PropertyType>the initialization method of a direct call is generated
    2. 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

bingToIs 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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.