Try   HackMD

淺談 RxSwift + MVVM 使用

Mon, Apr 25, 2022 9:30 AM

tags: RxSwfit MVVM

假設現在有一簡單註冊需求:

  1. 帳號輸入框;帳號最少 6 個字。
  2. 密碼輸入框;密碼最少 8 個字。
  3. 驗證密碼輸入框;驗證密碼需與密碼完全相同。
  4. 註冊送出按鈕;按下送出後檢查上述條件。
  5. 註冊成功;彈出提示 註冊成功,反之註冊失敗

現在在腦裡假想一下,該怎麼實作以上需求。

沒有意外通常都是實作 UITextFieldDelegate 判斷當前的 textField 後再處理需求。

一、實作範例

完整程式碼參閱 GitHub tag: v1。
tag: v2 為 viewModel 優化,將 input、output 拆分,使用上會更清楚。

1. 建立 viewModel

protocol RegisterViewModelPrototype {
   // 
}

class RegisterViewModel: RegisterViewModelPrototype {
    //
}

2. 定義 protocol

protocol RegisterViewModelPrototype {
    /// 註冊結果
    var registerResult: PublishRelay<RegisterViewModel.RegisterResult> { get }
    /// 帳號
    var accountString: BehaviorRelay<String?> { get }
    /// 密碼
    var passwordString: BehaviorRelay<String?> { get }
    /// 驗證密碼
    var verifyPasswordString: BehaviorRelay<String?> { get }
    /// 送出註冊
    func register()
}

3. ViewController binding

func bind(_ viewModel: RegisterViewModelPrototype) {
    viewModel
        .registerResult
        .subscribe(onNext: { [weak self] result in
            ...      
        })
        .disposed(by: disposeBag)
        
    ...
}

4. ViewModel 判斷實作

func register() {
    guard let accountString = accountString.value, accountString.count >= 6,
          let passwordString = passwordString.value, passwordString.count >= 8,
          let verifyPasswordString = verifyPasswordString.value,
          passwordString == verifyPasswordString  else {
              registerResult.accept(.failed)
              
              return
          }
    
    registerResult.accept(.successful)
}

二、MVVM

在開始談論 RxSwift 之前我們先理解一下 MVVM (Model–view–viewmodel),詳細原理請直接參照維基百科。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

用 MVVM 的好處是什麼?

  • 讓程式碼之間不再耦合,畫面控件、邏輯不會糾纏不清。
  • 再也不怕畫面改來改去。

三、RxSwift

RxSwift 就是 ReactiveX 的 Swift 版本,是一個函式響應式框架,遵循 Functional Reactive Programming(FRP) 的設計規範,它把事件封裝成訊號流,並採用觀察者模式來實現。

1. Observable / Observer

這兩個名詞是所有 RxSwift 初學者必定會接觸的東西同時這也是貫穿整個 RxSwift 的重點。

  • Observable (可觀察的對象)
    嬰兒
  • Observer (觀察者)
    父母

Observable 送出訊號時,Observer 收到並做相對應處理。
舉例:當嬰兒哭泣,爸媽立刻動身探視。

2. 常見用法

  • Observable

- BehaviorRelay

BehaviorSubject 去掉終止事件 onErroronCompleted

初始的時候可以帶預設值,會持有 value;訂閱的時候就會送出訊號。

- PublishRelay

PublishSubject 去掉終止事件 onErroronCompleted

初始的時候沒有帶預設值,不會持有 value;訂閱的時候不會送出訊號,被觸發才會。

- subscribe

  • Observer
public enum Event<Element> {
    case next(Element)
    case error(Swift.Error)
    case completed
}

接收 ObservableEvent 訊號,進行後續處理。

- DisposeBag

跟隨生命週期控制 訂閱事件 的釋放。

3. 常見錯誤

var string1 = BehaviorRelay<String?>(value: nil)
var string2 = PublishRelay<String>()

BehaviorRelayPublishRelay 本身為容器非變數,所以正確應寫 let 而非 var

4. 更多關於 RxSwift 的語法

請詳閱 RxSwift 中文文檔

四、總結

以上做法是非常淺入的寫法。

只需要實作幾個環節就能完成本文一開始的簡單需求,以上全部僅為個人的簡單見解如有錯誤請不吝指教。

希望可以一起進步。