RxSwift初體驗(yàn)之實(shí)戰(zhàn)演習(xí)

概述

Rx 通過(guò) Observable<Element>接口來(lái)表達(dá)計(jì)算型泛型抽象 (generic abstraction of computation) 的概念,而 RxSwift 是 Rx 的 Swift 版本。無(wú)疑,這個(gè)內(nèi)容非常龐大,所以我打算用真是代碼側(cè)面描述一下自己對(duì)使用的一些心得體會(huì)以一種稍微簡(jiǎn)單點(diǎn)的介紹方式來(lái)講解這個(gè)框架。

1.首先我們要了解幾個(gè)關(guān)鍵詞
(1)Variable
Variable表示一個(gè)可監(jiān)聽(tīng)的數(shù)據(jù)結(jié)構(gòu)。使用Variable,你可以監(jiān)聽(tīng)數(shù)據(jù)的變化,也可以把其他值綁定到它身上。

例子一
class VariableController: UIViewController {
    
    @IBOutlet weak var label: UILabel!
    var disposeBag = DisposeBag()
    var timer:Timer?
    var count = Variable(0)
    override func viewDidLoad() {
        super.viewDidLoad()
        timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector:#selector(VariableController.updateValue) , userInfo: nil, repeats: true)
        _ = count.asObservable().subscribe(onNext: { (num) in
            self.label?.text = "VariableValue:\(num)"
        }, onError: nil, onCompleted: nil, onDisposed: nil).addDisposableTo(self.disposeBag)
    }
    func updateValue(){
        count.value = count.value + 1
    }
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        timer?.invalidate()
    }
}
例子二
//我們?cè)趘iewmodel里面創(chuàng)建Variable的變量
var isValidLoading: Variable = Variable("")
self.isValidLoading.value = "show"
//在vc里面去監(jiān)聽(tīng)做操作
self.viewModel.isValidLoading.asObservable().subscribe(onNext: { (result) in
            if result == "show"{
                self.showLoading()
            }else{
                self.hideLoading()
            }
        }, onError: nil, onCompleted: nil, onDisposed: nil).addDisposableTo(self.disposeBag)
//注意這里的subscribe后會(huì)的到next(),必須通過(guò)onNext去取到里面的值

(2)Observable
Observable表示可監(jiān)聽(tīng)或者可觀察,也就是說(shuō)RxSwift的核心思想是可監(jiān)聽(tīng)的序列。并且,Observable sequence可以接受異步信號(hào),也就是說(shuō),信號(hào)是可以異步給監(jiān)聽(tīng)者的
Observable分為兩種
(1)在有限的時(shí)間內(nèi)會(huì)自動(dòng)結(jié)束(Completed/Error),比如一個(gè)網(wǎng)絡(luò)請(qǐng)求當(dāng)作一個(gè)序列,當(dāng)網(wǎng)絡(luò)請(qǐng)求完成的時(shí)候,Observable自動(dòng)結(jié)束,資源會(huì)被釋放
(2)信號(hào)不會(huì)自己結(jié)束,最簡(jiǎn)單的比如一個(gè)Timer,每隔一段時(shí)間發(fā)送一個(gè)新的信號(hào)過(guò)來(lái),這時(shí)候需要手動(dòng)取消監(jiān)聽(tīng),來(lái)釋放相應(yīng)的資源,又比如一個(gè)label.rac_text是一個(gè)Obserable,通常需要這樣調(diào)用addDisposableTo(disposeBag)來(lái)讓其在deinit,也就是所有者要釋放的時(shí)候,自動(dòng)取消監(jiān)聽(tīng)。

信號(hào)處理的順序
Observable有個(gè)隱式的約定,那就是在一個(gè)信號(hào)處理完成之前,不會(huì)發(fā)送下一個(gè)信號(hào),不管發(fā)送信號(hào)的線程是并發(fā)的or串行的。

someObservable
  .subscribe { (e: Event<Element>) in
      print("Event processing started")
      // processing
      print("Event processing ended")
  }
//只會(huì)出現(xiàn)
Event processing started
Event processing ended
Event processing started
Event processing ended
Event processing started
Event processing ended
//不會(huì)出現(xiàn)
Event processing started
Event processing started
Event processing ended
Event processing ended

實(shí)例

//我們監(jiān)聽(tīng)textfield的文字變化,然后,Log出text,當(dāng)button點(diǎn)擊的時(shí)候,取消這次監(jiān)聽(tīng)
class ObservableAndCancelController : UIViewController{
    var subscription:Disposable?
    @IBOutlet weak var textfield: UITextField!
    @IBAction func cancelObserve(sender: AnyObject) {
        subscription?.dispose()
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        subscription = textfield.rx.text.asObservable().subscribe(onNext:  { (text) in
            print(text)
        })
    }
}

map: 對(duì)信號(hào)(Element)進(jìn)行映射處理。比如輸入是String,影射到Bool
filter: 對(duì)信號(hào)(Element)進(jìn)行過(guò)濾處理。返回信號(hào),和輸入的信號(hào)是同一種類(lèi)型
combineLatest: 對(duì)兩種信號(hào)的值進(jìn)行結(jié)合??梢苑祷夭煌N類(lèi)的信號(hào)。

 let firstObserverable = firstTextfield.rx.text.map({"first" + $0})
     let secondObserverable = secondTextfield.rx.text.filter({$0.characters.count > 3})
      _ =  Observable.combineLatest(firstObserverable, secondObserverable, resultSelector:{ ($0 + $1,$0.characters.count + $1.characters.count)}).subscribe(onNext:  { (element) in
            print("combineLatest:\(element)")
      }, onError: nil, onCompleted: nil, onDisposed: nil).addDisposableTo(self.disposeBag)       
//打印
combineLatest:("first1234abcd", 13)
combineLatest:("first1234abcde", 14)
combineLatest:("first1234abcdef", 15)
combineLatest:("first1234abcdefg", 16)

Observerable可以用來(lái)處理任務(wù),并且異步返回Event信號(hào)(Next,Error,Completion)

//Observable就是處理輸入,并且把description發(fā)送出去
func createObserveable(object:AnyObject?)->Observable<String?>{
    return Observable.create({ observer in
        observer.onNext(object?.description)
        observer.onCompleted()
        return NopDisposable.instance
    })
}
_ = createObserveable(test).subscribe({ (event) in
      switch event{
      case .Next(let value):
          print(value)
      case .Completed:
          print("Completed")
      case .Error(let error):
          print(error)
      }
  })

創(chuàng)建一個(gè)Observable相當(dāng)容易,調(diào)用Observable.create,在必要的時(shí)候發(fā)送onNext,onError,onCompleted信號(hào)。然后返回一個(gè)Disposable用來(lái)取消信號(hào)
(3)bindTo
數(shù)據(jù)綁定是開(kāi)發(fā)的時(shí)候很常見(jiàn)的,比如根據(jù)文本的輸入動(dòng)態(tài)調(diào)整textfield的背景色,動(dòng)態(tài)調(diào)整按鈕的enable。亦或者根據(jù)textfield的輸入變化,動(dòng)態(tài)的去反饋到model層。如果你聽(tīng)過(guò)MVVM,那你肯定知道,MVVM的難點(diǎn)就是ViewModel與View的數(shù)據(jù)綁定問(wèn)題。

//我們?cè)趘iewmodel里面創(chuàng)建Observable的變量
var isValidSendButton: Observable<Bool>!
//在vc里面去和按鈕的是否點(diǎn)擊進(jìn)行綁定
var disposeBag = DisposeBag()
self.viewModel.isValidSendButton.asObservable().bindTo(self.sendBtn!.rx.isEnabled).addDisposableTo(self.disposeBag)

講到這里我們已經(jīng)可以簡(jiǎn)單的來(lái)嘗試做一下事情了

class ObservableAndCancelController : UIViewController{
    //userName 用來(lái)監(jiān)聽(tīng)輸入框的值
   //password 用來(lái)監(jiān)聽(tīng)輸入框的值
    var disposeBag = DisposeBag()
    //這里的UITextField和UIButton的布局就根據(jù)自己的想法實(shí)例化,這里沒(méi)有寫(xiě),所以直接運(yùn)行是沒(méi)有效果的
    var nameTextfield:UITextField?
    var passwordTextfield:UITextField?
    var registerButton:UIButton?
    
    var userName:Variable = Variable("")
    var password:Variable = Variable("")
    var validUserName:Observable<Bool>!
    var validPassword:Observable<Bool>!
    var isValidSendButton: Observable<Bool>!
    override func viewDidLoad() {
        super.viewDidLoad()
        self.nameTextfield?.rx.text.asObservable().subscribe(onNext:{ [weak self](result) in
            self?.userName.value = result!
        }, onError: nil, onCompleted: nil, onDisposed: nil).addDisposableTo(self.disposeBag)
        self.passwordTextfield?.rx.text.asObservable().subscribe(onNext:{ [weak self](result) in
            self?.password.value = result!
            }, onError: nil, onCompleted: nil, onDisposed: nil).addDisposableTo(self.disposeBag)
        
        validUserName = userName.asObservable().map({$0.characters.count >= 6}).shareReplay(1)
        validPassword = password.asObservable().map({$0.characters.count >= 8}).shareReplay(1)

        _ = validUserName.subscribe(onNext: { (valid) in
            self.nameTextfield?.backgroundColor = valid ? UIColor.clear:UIColor.lightGray
        }, onError: nil, onCompleted: nil, onDisposed: nil).addDisposableTo(self.disposeBag)
        _ = validPassword.subscribe(onNext: { (valid) in
            self.passwordTextfield?.backgroundColor = valid ? UIColor.clear:UIColor.lightGray
        }, onError: nil, onCompleted: nil, onDisposed: nil).addDisposableTo(self.disposeBag)//addDisposableTo(disposeBag)是為了自動(dòng)釋放
        isValidSendButton = Observable.combineLatest(validUserName, validPassword) {$0 && $1}
        isValidSendButton?.subscribe(onNext: {(result:Bool) in
            if result{
            self.registerButton?.isEnabled = true
            self.registerButton?.backgroundColor = UIColor.red
            }else{
            self.registerButton?.isEnabled = false
            self.registerButton?.backgroundColor = UIColor.darkGray
            }
        }, onError: nil, onCompleted: nil, onDisposed: nil).addDisposableTo(self.disposeBag)
        self.isValidSendButton.asObservable().bindTo(self.registerButton!.rx.isEnabled).addDisposableTo(self.disposeBag)
        self.registerButton?.rx.tap.shareReplay(1).subscribe(onNext: { (result) in
            print("Button tapped")
        }, onError: nil, onCompleted: nil, onDisposed: nil).addDisposableTo(self.disposeBag)
    }
}

以上是在網(wǎng)上的一些學(xué)習(xí)體會(huì)和自己的實(shí)戰(zhàn)總結(jié),講的不多,直講到一些基礎(chǔ)的使用方法,希望對(duì)入門(mén)的同學(xué)有些幫助,謝謝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文章內(nèi)部分圖片資源來(lái)自RayWenderlich.com 本文結(jié)合自己的理解來(lái)總結(jié)介紹一下RxSwift最基本的...
    FKSky閱讀 3,045評(píng)論 4 14
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,659評(píng)論 19 139
  • 發(fā)現(xiàn) 關(guān)注 消息 RxSwift入坑解讀-你所需要知道的各種概念 沸沸騰關(guān)注 2016.11.27 19:11*字...
    楓葉1234閱讀 2,938評(píng)論 0 2
  • 本篇文章介主要紹RxJava中操作符是以函數(shù)作為基本單位,與響應(yīng)式編程作為結(jié)合使用的,對(duì)什么是操作、操作符都有哪些...
    嘎啦果安卓獸閱讀 2,991評(píng)論 0 10
  • 記得第一次讀這本書(shū)是在高三,那些個(gè)慌亂匆忙的日子,我也沒(méi)有把它讀完,再次撿起來(lái),我不想敷衍了事。 第一次讀的時(shí)候就...
    Misty小透明閱讀 653評(píng)論 0 1

友情鏈接更多精彩內(nèi)容