RxSwift經常使用框架、MVVM

函數響應式編程 清晰簡潔、易讀、易維護的代碼,下面咱們看下 RxSwift 的最佳搭檔:MVVMhtml

MVVM

原先經常使用的架構:MVC

image

  • Model:數據層。負責讀寫數據,保存 App 狀態等面試

  • Controller:業務邏輯層。負責業務邏輯、事件響應、數據加工等工做算法

缺點:編程

  • ViewController 既扮演了 View 的角色,又扮演了 ViewController 的角色
  • 而 Model 在 VIewController 中又能夠直接與 View 進行交互
  • 當 App 交互複雜的時候,就會發現 ViewController 將變得十分臃腫,大量代碼被添加到控制器中,使得控制器負擔太重。
MVVM

image

優勢:

  • 能夠對 ViewController 進行瘦身
  • 實現邏輯視圖的複用。好比一個 ViewModel 能夠綁定到不一樣的 View 上,讓多個 View 重用相同的視圖邏輯。
  • 並且使用 MVVM 能夠大大下降代碼的耦合性,方便進行單元測試以及維護,也方便多人協做開發(好比一我的負責邏輯實現,一我的負責 UI 實現)。

缺點:markdown

  • 相較於 MVC,使用 MVVM 會輕微的增長代碼量,可是整體上減小了代碼的複雜性。
  • 還有就是有必定的學習成本(如何數據綁定等)。

做爲一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是個人iOS交流圈: 無論你是小白仍是大牛歡迎入駐!! 分享內容包括跳槽面試資源、逆向安防、算法、架構設計、多線程,網絡進階,還有底層、音視頻、Flutter等等......網絡

本身根據梳理網絡來的的開發經驗總結的學習方法,無償分享給你們。更多資源,須要的話均可以自行來獲取下載。 +裙:196800191、 或者是+ WX(XiAZHiGardenia)免費獲取! 獲取面試資料 簡歷模板 一塊兒交流技術資源集合多線程


## MVVM

MVVM 是 Model-View-ViewModel 的簡寫。若是你已經對 MVC 很是熟悉了,那麼上手 MVVM 也是很是容易的。架構


MVC

image

MVC 是 Model-View-Controller 的簡寫。MVC 主要有三層:app

  • Model 數據層,讀寫數據,保存 App 狀態
  • View 頁面層,和用戶交互,向用戶顯示頁面,反饋用戶行爲
  • ViewController 邏輯層,更新數據,或者頁面,處理業務邏輯

MVC 能夠幫助你很好的將數據,頁面,邏輯的代碼分離開來。使得每一層相對獨立。這樣你就可以將一些可複用的功能抽離出來,化繁爲簡。只不過,一旦 App 的交互變複雜,你就會發現 ViewController 將變得十分臃腫。大量代碼被添加到控制器中,使得控制器負擔太重。此時,你就須要想辦法將控制器裏面的代碼進一步地分離出來,對 APP 進行從新分層。而 MVVM 就是一種進階的分層方案。ide


MVVM

image

MVVM 和 MVC 十分相識。只不過他的分層更加詳細:

  • Model 數據層,讀寫數據,保存 App 狀態
  • View 頁面層,提供用戶輸入行爲,而且顯示輸出狀態
  • ViewModel 邏輯層,它將用戶輸入行爲,轉換成輸出狀態
  • ViewController 主要負責數據綁定

沒錯,ViewModel 如今是邏輯層,而控制器只須要負責數據綁定。如此一來控制器的負擔就減輕了許多。而且 ViewModel 與控制器以及頁面相獨立。那麼,你就能夠跨平臺使用它。你也能夠很容易地測試它。


示例

這裏咱們將用 MVVM 來重構輸入驗證

image

重構前:

class SimpleValidationViewController : ViewController {

    ...

    override func viewDidLoad() {
        super.viewDidLoad()

        ...

        let usernameValid = usernameOutlet.rx.text.orEmpty
            .map { $0.characters.count >= minimalUsernameLength }
            .share(replay: 1)

        let passwordValid = passwordOutlet.rx.text.orEmpty
            .map { $0.characters.count >= minimalPasswordLength }
            .share(replay: 1)

        let everythingValid = Observable.combineLatest(
              usernameValid,
              passwordValid
            ) { $0 && $1 }
            .share(replay: 1)

        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)

        doSomethingOutlet.rx.tap
            .subscribe(onNext: { [weak self] in self?.showAlert() })
            .disposed(by: disposeBag)
    }

    ...

}

複製代碼

ViewModel

image

ViewModel 將用戶輸入行爲,轉換成輸出的狀態:

class SimpleValidationViewModel {

    // 輸出
    let usernameValid: Observable<Bool>
    let passwordValid: Observable<Bool>
    let everythingValid: Observable<Bool>

    // 輸入 -> 輸出
    init(
        username: Observable<String>,
        password: Observable<String>
        ) {

        usernameValid = username
            .map { $0.characters.count >= minimalUsernameLength }
            .share(replay: 1)

        passwordValid = password
            .map { $0.characters.count >= minimalPasswordLength }
            .share(replay: 1)

        everythingValid = Observable.combineLatest(usernameValid, passwordValid) { $0 && $1 }
            .share(replay: 1)

    }
}

複製代碼

輸入:

  • username 輸入的用戶名
  • password 輸入的密碼

輸出:

  • usernameValid 用戶名是否有效
  • passwordValid 密碼是否有效
  • everythingValid 全部輸入是否有效

在 init 方法內部,將輸入轉換爲輸出。


ViewController

ViewController 主要負責數據綁定:

class SimpleValidationViewController : ViewController {

    ...

    private var viewModel: SimpleValidationViewModel!

    override func viewDidLoad() {
        super.viewDidLoad()

        ...

        viewModel = SimpleValidationViewModel(
            username: usernameOutlet.rx.text.orEmpty.asObservable(),
            password: passwordOutlet.rx.text.orEmpty.asObservable()
        )

        viewModel.usernameValid
            .bind(to: passwordOutlet.rx.isEnabled)
            .disposed(by: disposeBag)

        viewModel.usernameValid
            .bind(to: usernameValidOutlet.rx.isHidden)
            .disposed(by: disposeBag)

        viewModel.passwordValid
            .bind(to: passwordValidOutlet.rx.isHidden)
            .disposed(by: disposeBag)

        viewModel.everythingValid
            .bind(to: doSomethingOutlet.rx.isEnabled)
            .disposed(by: disposeBag)

        doSomethingOutlet.rx.tap
            .subscribe(onNext: { [weak self] in self?.showAlert() })
            .disposed(by: disposeBag)
    }

    ...

}

複製代碼

輸入:

  • username 將輸入的用戶名傳入 ViewModel
  • password 將輸入的密碼傳入 ViewModel

輸出:

  • usernameValid 用用戶名是否有效,來控制提示語是否隱藏,密碼輸入框是否可用
  • passwordValid 用密碼是否有效,來控制提示語是否隱藏
  • everythingValid 用二者是否同時有效,來控制按鈕是否可點擊

當 App 的交互變複雜時,你仍然能夠保持控制器結構清晰。這樣能夠大大的提高代碼可讀性。未來代碼維護起來也就會容易許多了。


示例

 Github Signup 來演示如何使用 MVVM

注意⚠️:這裏介紹的 MVVM 並非嚴格意義上的 MVVM。但咱們一般都管它叫 MVVM,並且它配合 RxSwift 使用起來很是方便。如需瞭解什麼是嚴格意義上的 MVVM,請參考微軟的 The MVVM Pattern

相關文章
相關標籤/搜索