在ReactiveSwift中,<~運(yùn)算符實(shí)現(xiàn)了數(shù)據(jù)源(Source)到數(shù)據(jù)目標(biāo)(Target)之間的綁定關(guān)系,實(shí)現(xiàn)了數(shù)據(jù)源的值發(fā)生變化時(shí),數(shù)據(jù)目標(biāo)同時(shí)得到更新暴浦,實(shí)際應(yīng)用一般是在UI控件的值隨與之綁定的ViewModel的值同步更新。
例如一個(gè)UILabel晓锻,綁定到ViewModel中的labelValue: MutableProperty
let label = UILabel()
label.reactive.text <~ viewModel.labelValue
之后歌焦,一旦ViewModel的labelValue值發(fā)生變化,則同步到視圖中的label進(jìn)行顯示砚哆,一次綁定独撇,終生享用,無需人工干預(yù)躁锁。
那么纷铣,這種綁定關(guān)系如何實(shí)現(xiàn)的,下面進(jìn)行源碼分析
從 <~的源碼開始分析入手:
<~函數(shù)在BindingTargetProvider協(xié)議中聲明战转,調(diào)用這個(gè)方法是由表達(dá)式左邊的對象作為Self發(fā)起的
BindingTarget <~ BindingSource |
e.g. label.reactive.text <~ viewModel.labelValue |
首先我們分析BindingTarget
BindingTarget主要包含一個(gè)(Value) -> Void 的action閉包搜立,在構(gòu)造的時(shí)候傳入action逃逸閉包
通過讓UILabel遵守ReactiveExtensionProvider協(xié)議,并擴(kuò)展Reactive where Base: UILabel方式槐秧,為UILabel增加Reactive擴(kuò)展屬性
makeBindingTarget { 1 } 實(shí)現(xiàn)了BindingTarget的self.base.text = value的賦值動(dòng)作啄踊,也是在<~運(yùn)算符中的provider.bindingTarget.action動(dòng)作,就是這里的賦值動(dòng)作刁标,至此颠通,BindingTarget這端的動(dòng)作及協(xié)議實(shí)現(xiàn)完成,下面來看BindingSource這邊需要完成的協(xié)議膀懈。
我們來實(shí)現(xiàn)一個(gè)簡單的AA類顿锰,讓這個(gè)類同時(shí)符合BindingTarget和BindingSource兩個(gè)協(xié)議的要求
AA類的實(shí)現(xiàn)點(diǎn):
在構(gòu)造時(shí),自身保存一對(signal, observer)
擴(kuò)展AA類遵守BindingSource協(xié)議启搂,聲明producer計(jì)算屬性硼控,在SignalProducer的startHandler中,調(diào)用自身的observer發(fā)送值消息胳赌,并將SignalProducer構(gòu)造的observer添加至自身signal中保存
擴(kuò)展AA類遵守BindingTarget協(xié)議牢撼,聲明tareget計(jì)算屬性,返回makeBindingTarget { $0.name = $1 }匈织,完成賦值動(dòng)作,這里多講一點(diǎn)的就是,makeBindingTarget是對BindingTarget的二次封裝缀匕,在BindingTarget構(gòu)造中纳决,action是(Value) -> Void類型,這里的makeBindingTarget傳參是(Base, Value) -> Void類型乡小,展開makeBindingTarget方法后阔加,可以看到它是怎么進(jìn)行二次封裝的,添加了Base屬性在其中满钟。
-
聲明changeValue(value: String)方法胜榔,在賦值過程中,調(diào)用一次自身的observer發(fā)送值消息湃番,這里的changeValue動(dòng)作類似MutableProperty對值類型的封裝過程夭织,并這里作了簡化便于理解原理,在MutableProperty的賦值過程中吠撮,是調(diào)用了內(nèi)部的Box對存儲(chǔ)的值進(jìn)行了一次封裝尊惰,并涉及到原子操作。
image.png
調(diào)用AA.changeValue后泥兰,一次調(diào)用AA自身的observer.send -> AA.producer.observer.send -> provider.bindingTarget.action 最終完成賦值動(dòng)作