代碼還是要?jiǎng)邮謱?xiě),一起來(lái)用RxSwift來(lái)寫(xiě)一個(gè)簡(jiǎn)單的Demo吧东抹,動(dòng)起手來(lái)秩冈,不要懶本缠,因?yàn)檫@個(gè)真的很簡(jiǎn)單,但是還是能學(xué)到一些東西的入问。
本篇文章的完整項(xiàng)目及以后的RxSwift相關(guān)Demo都在: 點(diǎn)擊這里丹锹。
我們預(yù)期的結(jié)果是這樣:
準(zhǔn)備
開(kāi)始前,先在storyboard中拖幾個(gè)控件芬失。
當(dāng)然楣黍,如果你想手寫(xiě)也是可以的,storyboard比較省時(shí)間而已棱烂。效果如下圖:
<br />
<br />
然后import RxSwift
和RxCocoa
,并定義以下屬性:
import RxSwift
import RxCocoa
let minUsernameLength = 5
let maxUsernameLength = 10
let minPasswordLength = 5
let maxPasswordLength = 16
let disposBag = DisposeBag()
將控件拖至相應(yīng)的ViewController
:
@IBOutlet weak var usernameTF: UITextField!
@IBOutlet weak var usernameLB: UILabel!
@IBOutlet weak var passwordTF: UITextField!
@IBOutlet weak var passwordLB: UILabel!
@IBOutlet weak var loginButton: UIButton!
對(duì)輸入字符串進(jìn)行判斷
override func viewDidLoad() {
super.viewDidLoad()
let usernameValid = usernameTF.rx_text
.map{$0.characters.count >= minUsernameLength && $0.characters.count <= maxUsernameLength } //map函數(shù) 對(duì)text進(jìn)行處理
.shareReplay(1)
let passwordValid = passwordTF.rx_text
.map{$0.characters.count >= minPasswordLength && $0.characters.count < maxPasswordLength } //map函數(shù) 對(duì)text進(jìn)行處理
.shareReplay(1)
}
首先租漂,定義一個(gè)布爾值:usernameValid
來(lái)接收usernameTF
字符個(gè)數(shù)是否符合要求,同理passwordValid
接收usernameTF
字符個(gè)數(shù)是否符合要求颊糜。
.map負(fù)責(zé)對(duì)UITextField中的字符進(jìn)行處理哩治,判斷字符長(zhǎng)度,是否符合要求衬鱼,將判斷的值返回給usernameValid
和passwordValid
业筏。
關(guān)于map
函數(shù),可以參考這篇文章鸟赫。
shareReplay()
是RxSwift提供的一個(gè)流操作函數(shù)蒜胖,它是以重播的方式通知自己的訂閱者消别,保證在觀察者訂閱這個(gè)流的時(shí)候始終都能回播最后N個(gè),shareReplay(1)
表示重播最后一個(gè)翠勉。
然后妖啥,我們需要根據(jù)用戶名和密碼輸入是否全部符合要求,來(lái)控制登錄按鈕是否可以點(diǎn)擊:
let everythingValid = Observable.combineLatest(usernameValid, passwordValid) { (usernameValid, passwordValid) -> Bool in
usernameValid && passwordValid
}
當(dāng)usernameValid
和 passwordValid
同時(shí)為true
時(shí)对碌,everythingValid
才為true
荆虱,我們用everythingValid
來(lái)控制登錄按鈕是否可以點(diǎn)擊。
上邊的代碼可以簡(jiǎn)化成:
let everythingValid = Observable.combineLatest(usernameValid, passwordValid) { $0 && $1 }
.shareReplay(1)
原理參考這篇文章朽们。
綁定
usernameValid
.bindTo(passwordTF.rx_enabled) //username通過(guò)驗(yàn)證怀读,passwordTF才可以輸入
.addDisposableTo(disposBag)
將usernameValid
和passwordTF.rx_enabled
綁定,即用usernameValid
來(lái)控制passwordTF
是否可以輸入的狀態(tài)骑脱。
注意:這里我們用usernameValid
和passwordTF
的rx_enabled
綁定菜枷。通過(guò)這個(gè)綁定,只有當(dāng)usernameValid
為true
時(shí)叁丧,passwordTF
才是可以輸入的狀態(tài)啤誊,也就是我們需要在用戶名長(zhǎng)度正確的時(shí)候,才可以輸入密碼拥娄,否則蚊锹,密碼輸入框?yàn)椴豢沙鋈霠顟B(tài)。
bindTo
就是RxSwfit
中用來(lái)進(jìn)行值綁定的函數(shù)稚瘾。
addDisposableTo(disposBag)
訂閱信號(hào)會(huì)產(chǎn)生Disposable牡昆。如果不銷毀,那么這些生成的Disposable將會(huì)一直存在摊欠,這無(wú)疑是非常耗內(nèi)存的丢烘。所以,想要釋放無(wú)用的資源些椒,可以調(diào)用dispose播瞳,但是直接調(diào)用dispose會(huì)有一個(gè)問(wèn)題,就是如果調(diào)用時(shí)機(jī)不對(duì)免糕,可能會(huì)影響到程序的正常運(yùn)行狐史。所以我們可以用addDisposableTo(disposeBag)
。類似于autoreleasepool
说墨,由它處理資源的自動(dòng)銷毀骏全。是不是有點(diǎn)像mrc
和arc
的區(qū)別,那么選哪個(gè)更好尼斧,就不用說(shuō)了姜贡,肯定是使用addDisposableTo(disposBag)
。
接下來(lái)棺棵,將usernameTF
下邊的提示label
和usernameValid
綁定:
usernameValid
.bindTo(usernameLB.rx_hidden) //username通過(guò)驗(yàn)證楼咳,usernameLB警告消失
.addDisposableTo(disposBag)
這樣熄捍,當(dāng)用戶名符合要求的時(shí)候,警告消息就會(huì)隱藏母怜,當(dāng)不符合時(shí)余耽,又會(huì)再度出現(xiàn)。
接下來(lái)苹熏,將其他的屬性都綁定起來(lái):
passwordValid
.bindTo(passwordLB.rx_hidden)
.addDisposableTo(disposBag)
everythingValid
.bindTo(loginButton.rx_enabled) // 用戶名密碼都通過(guò)驗(yàn)證碟贾,才可以點(diǎn)擊按鈕
.addDisposableTo(disposBag)
loginButton.rx_tap //綁定button點(diǎn)擊事件
.subscribeNext { [weak self] in
self?.showAlert()
}
.addDisposableTo(disposBag)
在viewDidLoad()
方法外,定于一個(gè)方法轨域,用來(lái)顯示提示信息:
func showAlert() {
let alertView = UIAlertView(
title: "成功",
message: "登錄成功",
delegate: nil,
cancelButtonTitle: "OK"
)
alertView.show()
}
完成
搞定袱耽,運(yùn)行你的程序吧,嘗試輸入正確和錯(cuò)誤位數(shù)的用戶名/密碼干发,試試看朱巨。
當(dāng)都輸入正確的時(shí)候,結(jié)果如下圖:
本篇文章的完整項(xiàng)目及以后的RxSwift相關(guān)Demo都在: 點(diǎn)擊這里枉长。
以后就可以在自己應(yīng)用中使用RxSwift
來(lái)寫(xiě)登錄/注冊(cè)界面了冀续。當(dāng)然,這才算是剛剛?cè)腴TRxSwift
必峰。以后的路還長(zhǎng)洪唐,要學(xué)的還很多。路漫漫其修遠(yuǎn)兮 吾將上下而求索自点。