零基礎(chǔ)也能看懂的 RxSwift 官方 Example 解析(1) Bindings

概述

很多小伙伴在初學(xué) RxSwift 時(shí)嚷兔,在面對(duì)大量的操作符和各種抽象的概念時(shí)可能都會(huì)感到無從下手盹愚,但其實(shí)官方提供的 Example 就能夠很方便的幫助我們學(xué)習(xí) RxSwift 的各種概念以及如何與 MVVM 相結(jié)合师崎。畢竟直接看實(shí)際的運(yùn)用場景比看抽象的概念要容易理解的多咐柜。

我個(gè)人認(rèn)為 RxSwift 的核心其實(shí)很簡單师骗,就是把要操作的事件黔龟、屬性都抽象成一個(gè)個(gè)Observable妇智,剩下的變換、組合氏身、過濾巍棱、響應(yīng)(訂閱)、線程調(diào)度蛋欣、生命周期管理都是你對(duì) Observable 的加工和處理航徙。如果你真的理解了什么是 Observable,哪些東西可以被包裝成 Observable 那么你已經(jīng)成功了一半啦陷虎,就像你剛學(xué)面向?qū)ο缶幊痰教ぃ愣耸裁词菍?duì)象,哪些東西可以被抽象成對(duì)象以后泻红,后面的學(xué)習(xí)是不是順利了很多呢夭禽。

其實(shí)初學(xué)的時(shí)候真的不用在面對(duì)大量的操作符時(shí)困惑,也不要有怕難的心態(tài)谊路,覺得這么多東西我得記到什么時(shí)候讹躯。可以先看一遍文檔有能力的也可以看看源碼缠劝。用的多了你會(huì)發(fā)現(xiàn)和我們平常寫代碼一樣潮梯,常用的 Api 就那些,其他用的少的真忘記的時(shí)候再翻翻文檔就好惨恭。(中文文檔 RxSwift-Chinese-Documentation)

好了廢話不多說秉馏,本篇所有示例代碼在 RxSwift 官方項(xiàng)目中就有,下載完了直接運(yùn)行即可脱羡。

可以看到官方為我們分了三塊內(nèi)容萝究,

  • iPhone Example
  • TableView 和 CollectionView Example
  • 綜合的 Example

本篇文章我們先從這些 Demo 里最簡單的 Bindings 說起。

Adding numbers

先看運(yùn)行效果

有三個(gè) UITextField 任何一個(gè) UITextField 輸入內(nèi)容時(shí)锉罐,把三者相加帆竹,在最底部 UILabel 顯示結(jié)果。

這是一個(gè)很簡單的響應(yīng)式編程的例子脓规,這個(gè)頁面主要由四個(gè)元素組成

@IBOutlet weak var number1: UITextField!
@IBOutlet weak var number2: UITextField!
@IBOutlet weak var number3: UITextField!
@IBOutlet weak var result: UILabel!

先考慮一下以往我們會(huì)怎么實(shí)現(xiàn):

  1. 監(jiān)聽三個(gè) UITextField 的文本框改變(Delegate栽连、KVONSNotificationCenteraddTarget)秒紧。
  2. 在回調(diào)方法中將三個(gè) UITextField 輸入內(nèi)容轉(zhuǎn)成 Int 相加并賦值給 UILabel绢陌。

原生實(shí)現(xiàn)最大的問題在于,無論哪種方式熔恢,監(jiān)聽文本框內(nèi)容改變的代碼都不是那么的優(yōu)雅脐湾。

看一下用 RxSwift 如何實(shí)現(xiàn)〖ㄆ福回想我們剛剛所說的核心沥割,把屬性或者事件抽象成 Observable,再對(duì) Observable 進(jìn)行操作凿菩。

  1. 包裝 (把三個(gè) UITextField 輸入的內(nèi)容抽象成三個(gè) Observable)
number1.rx.text.orEmpty
number2.rx.text.orEmpty
number3.rx.text.orEmpty
  1. 組合 (把三個(gè)Observable組合,并將每一個(gè)值轉(zhuǎn)成 Int 類型相加)帜讲。
Observable.combineLatest(number1.rx.text.orEmpty, number2.rx.text.orEmpty, number3.rx.text.orEmpty) { textValue1, textValue2, textValue3 -> Int in
    return (Int(textValue1) ?? 0) + (Int(textValue2) ?? 0) + (Int(textValue3) ?? 0)
 }

文檔中為我們描述的 combineLatest 的作用衅谷。

當(dāng)多個(gè) Observables 中任何一個(gè)發(fā)出一個(gè)元素,就發(fā)出一個(gè)元素似将。這個(gè)元素是由這些 Observables 中最新的元素获黔,通過一個(gè)函數(shù)組合起來的。


說的再直白一點(diǎn)就是在验,這三個(gè) UITextField 任意一個(gè)有新值的時(shí)候都會(huì)被組合成新的Observable玷氏。

  1. 轉(zhuǎn)換 (把 Int 類型轉(zhuǎn)換成 String 類型)
.map { $0.description }
  1. 響應(yīng) (把值綁定到 UILabel)
.bind(to: result.rx.text)
  1. 管理生命周期
.disposed(by: disposeBag)

怎么樣是不是很簡單呢,只需要6行代碼我們就完成了這個(gè)需求腋舌。

SimpleValidation

運(yùn)行效果


  • 當(dāng)用戶輸入用戶名時(shí)盏触,如果用戶名不足 5 個(gè)字就顯示紅色提示語,并且無法輸入密碼块饺,當(dāng)用戶名符合要求時(shí)才可以輸入密碼赞辩。
  • 同樣的當(dāng)用戶輸入的密碼不到 5 個(gè)字時(shí)也顯示紅色提示語。
  • 當(dāng)用戶名和密碼有一個(gè)不符合要求時(shí)底部的綠色按鈕不可點(diǎn)擊授艰,只有當(dāng)用戶名和密碼同時(shí)有效時(shí)按鈕才可點(diǎn)擊辨嗽。
  • 當(dāng)點(diǎn)擊綠色按鈕后彈出一個(gè)提示框

頁面由以下元素組成

/// 用戶名
@IBOutlet weak var usernameOutlet: UITextField!
/// 用戶名紅色提示語
@IBOutlet weak var usernameValidOutlet: UILabel!

/// 密碼
@IBOutlet weak var passwordOutlet: UITextField!
/// 密碼紅色提示語
@IBOutlet weak var passwordValidOutlet: UILabel!
/// 按鈕
@IBOutlet weak var doSomethingOutlet: UIButton!

還是先考慮一下以往我們會(huì)怎么實(shí)現(xiàn):

  1. 監(jiān)聽兩個(gè) UITextField 的文本框改變(DelegateKVO淮腾、NSNotificationCenter糟需、addTarget)。
  2. 在回調(diào)方法中判斷用戶名是否符合要求谷朝,用判斷結(jié)果去設(shè)置提示語是否隱藏和密碼框是否可以輸入洲押。
  3. 在回調(diào)方法中判斷密碼是否符合要求,用判斷結(jié)果去設(shè)置提示語是否隱藏徘禁。
  4. 拿到前兩個(gè)判斷的結(jié)果诅诱,當(dāng)前兩個(gè)的結(jié)果都為真時(shí),按鈕可以點(diǎn)擊送朱。
  5. 添加按鈕點(diǎn)擊事件娘荡。

看一下用 RxSwift 如何實(shí)現(xiàn)干旁。還是我們剛剛所說的核心,把屬性或者事件抽象成 Observable炮沐,再對(duì) Observable 進(jìn)行操作争群。

  1. 用戶名格式是否正確 (變換)
let usernameValid = usernameOutlet.rx.text.orEmpty
.map { $0.count >= minimalUsernameLength }
.share(replay: 1)
  1. 密碼格式是否正確 (變換)
let passwordValid = passwordOutlet.rx.text.orEmpty
 .map { $0.count >= minimalPasswordLength }
 .share(replay: 1)
  1. 兩者都正確(組合 ,combineLatest 作用上面介紹過大年,再鞏固一下)
let everythingValid = Observable.combineLatest(usernameValid, passwordValid) { $0 && $1 }
.share(replay: 1)

這里你可能比較疑惑這個(gè) .share(replay: 1) 是干嘛的换薄。

通俗一點(diǎn)說,當(dāng)有多個(gè)訂閱者去訂閱同一個(gè) Observable 的時(shí)候翔试,我們不希望 Observable 每次有新的訂閱者都去執(zhí)行轻要。

  1. 響應(yīng)
usernameValid
.bind(to: passwordOutlet.rx.isEnabled)
.disposed(by: disposeBag)
usernameValid
.bind(to: usernameValidOutlet.rx.isHidden)
.disposed(by: disposeBag)
passwordValid
.bind(to: passwordValidOutlet.rx.isHidden)
.disposed(by: disposeBag)
everythingValid
.bind(to: doSomethingOutlet.rx.isEnabled)
.disposed(by: disposeBag)

由于 .share(replay: 1) 的存在,這個(gè)判斷密碼或者用戶名是否合法的操作垦缅,不管以后被多少人訂閱冲泥,只會(huì)判斷一次,這樣可以避免不必要的資源消耗壁涎。

  1. 按鈕添加點(diǎn)擊事件
doSomethingOutlet.rx.tap
.subscribe(onNext: { [weak self] _ in self?.showAlert() })
.disposed(by: disposeBag)

當(dāng)然這步我們是可以通過擴(kuò)展的方式讓他更加優(yōu)雅的凡恍,這篇我們不做過多講解。

最后說句題外話怔球,學(xué)東西還是要從簡單的學(xué)起嚼酝,這樣會(huì)多一些正面積極的反饋,就像是打游戲總會(huì)一段時(shí)間就有一個(gè)小的獎(jiǎng)勵(lì)竟坛,刺激你繼續(xù)玩下去闽巩。如果一上來就看大量的操作符,各種概念和源碼流码,挫敗感一大就不想學(xué)了又官。

下一篇將更新如何與 MVVM 結(jié)合做一個(gè) GitHub 的注冊(cè)界面。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末漫试,一起剝皮案震驚了整個(gè)濱河市六敬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驾荣,老刑警劉巖外构,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異播掷,居然都是意外死亡审编,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門歧匈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來垒酬,“玉大人,你說我怎么就攤上這事】本浚” “怎么了矮湘?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長口糕。 經(jīng)常有香客問我缅阳,道長,這世上最難降的妖魔是什么景描? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任十办,我火速辦了婚禮,結(jié)果婚禮上超棺,老公的妹妹穿的比我還像新娘向族。我一直安慰自己,他們只是感情好说搅,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布炸枣。 她就那樣靜靜地躺著,像睡著了一般弄唧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上霍衫,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天候引,我揣著相機(jī)與錄音,去河邊找鬼敦跌。 笑死澄干,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的柠傍。 我是一名探鬼主播麸俘,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼惧笛!你這毒婦竟也來了从媚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤患整,失蹤者是張志新(化名)和其女友劉穎拜效,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體各谚,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡紧憾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昌渤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赴穗。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出般眉,到底是詐尸還是另有隱情了赵,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布煤篙,位于F島的核電站斟览,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏辑奈。R本人自食惡果不足惜苛茂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸠窗。 院中可真熱鬧妓羊,春花似錦、人聲如沸稍计。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽臣嚣。三九已至净刮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間硅则,已是汗流浹背淹父。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怎虫,地道東北人暑认。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像大审,于是被迫代替她去往敵國和親蘸际。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 前言RxSwift的目的是讓數(shù)據(jù)/事件流和異步任務(wù)能夠更方便的序列化處理徒扶,能夠使用Swift進(jìn)行響應(yīng)式編程粮彤。 本文...
    努力奔跑的小男孩閱讀 1,871評(píng)論 0 3
  • 概述 RxSwift顧名思義是Swift的一種框架,您或許曾經(jīng)聽說過「響應(yīng)式編程」(Reactive Progra...
    Mr大喵喵閱讀 1,856評(píng)論 3 4
  • 今天是星期六酷愧,如果不算今天的話驾诈,開學(xué)已經(jīng)一周了,時(shí)間過得真快叭茉 乍迄!我很懷念這一周的生活,從進(jìn)教室那一刻起……我發(fā)現(xiàn)整...
    依卓1閱讀 219評(píng)論 0 2
  • “我已經(jīng)老了士败〈沉剑”小說的開篇如是寫道褥伴。 翻開書,眼前漸漸顯現(xiàn)出這樣一幅畫面漾狼,風(fēng)燭殘年重慢、容顏備受歲月摧殘的老人在昏黃的...
    夜雨燈下客閱讀 471評(píng)論 0 3
  • 第八篇(周末回家) 小耀英和媽媽乘車到學(xué)校以后,耀英很快便找到了自己的宿舍和班級(jí)位置逊躁,然后媽媽幫著小耀英把被子...
    MrYichen閱讀 194評(píng)論 0 0