iOS 頁(yè)面架構(gòu)模式:VIP

原創(chuàng):知識(shí)探索型文章
創(chuàng)作不易,請(qǐng)珍惜,之后會(huì)持續(xù)更新,不斷完善
個(gè)人比較喜歡做筆記和寫總結(jié),畢竟好記性不如爛筆頭哈哈,這些文章記錄了我的IOS成長(zhǎng)歷程,希望能與大家一起進(jìn)步
溫馨提示:由于簡(jiǎn)書不支持目錄跳轉(zhuǎn),大家可通過(guò)command + F 輸入目錄標(biāo)題后迅速尋找到你所需要的內(nèi)容

目錄

  • 一、簡(jiǎn)介
  • 二、VIP Cycle
  • 三、總結(jié)
  • 參考資料

一、簡(jiǎn)介

iOS同學(xué)一定了解或使用過(guò)一些常用的iOS頁(yè)面架構(gòu)模式,比如MVCMVVM、MVP,甚至是VIPER。當(dāng)MVCMVVM、MVP對(duì)于某些復(fù)雜頁(yè)面不夠用、而你又討厭VIPER時(shí),不妨試試Clean SwiftVIP)這種架構(gòu)。本文將對(duì)此架構(gòu)的原理和實(shí)踐方式做一個(gè)詳細(xì)的說(shuō)明以幫助感興趣的同學(xué)快速入門。

Clean Swift(也稱作VIP) 最初是由 Raymond Law 在他的網(wǎng)站 clean-swift.com 上提出的。 其背后思想是在遵循 Uncle Bob 的Clean Architecture中的主要思想的同時(shí),解決龐大視圖控制器問(wèn)題。

在使用Clean Swift模式時(shí),我們可以將頁(yè)面或頁(yè)面上的某一模塊看作一個(gè)場(chǎng)景。理論上,每個(gè)場(chǎng)景由大約6個(gè)組件構(gòu)成:

  • View Controller (視圖控制器,包括 xibstoryboard)
  • Interactor(交互器)
  • Presenter(展示器)
  • Model
  • Router(路由器??蛇x)
  • Worker (工作器,可以看作 helper??蛇x)

其中,視圖控制器(V)、交互器(I)和展示器(P)是 Clean Swift 的三個(gè)主要組件。 它們作為彼此的輸入和輸出,如下圖所示:

視圖控制器的輸出連接到交互器的輸入,交互器的輸出連接到展示器的輸入,展示器的輸出連接到視圖控制器的輸入。 這意味著控制流和數(shù)據(jù)流始終是單向的。這被稱為 VIP Cycle。


二、VIP Cycle

Clean Swift 架構(gòu)使用VIP Cycle來(lái)幫助你分離代碼邏輯。VIP CycleViewController、InteractorPresenter組成。ViewController 負(fù)責(zé)顯示,Interactor 負(fù)責(zé)業(yè)務(wù)邏輯,Presenter 負(fù)責(zé)展示邏輯。

ViewController(視圖控制器)

ViewController是在 VIP Cycle 中第一個(gè)觸發(fā)動(dòng)作的類。它的作用如下:

  • 定義一個(gè)場(chǎng)景并包含一個(gè)或多個(gè)視圖。
  • 持有InteractorRouter 的實(shí)例。
  • 將視圖中的動(dòng)作封裝成一個(gè) Request 請(qǐng)求傳遞給 Interactor(輸出),并將 Presenter 觸發(fā)的動(dòng)作作為ViewController的輸入。
Interactor(交互器)

包含該場(chǎng)景所有的業(yè)務(wù)邏輯(這對(duì)編寫單元測(cè)試好處極大,因?yàn)闇y(cè)試 Interactor時(shí),該場(chǎng)景中所有的業(yè)務(wù)邏輯都經(jīng)過(guò)了測(cè)試)。

  • 持有 Presenter 的實(shí)例。
  • 根據(jù)輸入(來(lái)自 ViewControllerRequest),指揮 Worker 進(jìn)行操作(比如從數(shù)據(jù)庫(kù)、網(wǎng)絡(luò)獲取數(shù)據(jù))。完成操作時(shí),將從 Worker 處獲取到的原始數(shù)據(jù)封裝成 Response 傳遞給 Presenter

注意:Interactor 不需要也不應(yīng)該導(dǎo)入UIKit。

Presenter(展示器)

接收到 Interactor 傳遞的 Response 后,Presenter 將原始數(shù)據(jù)轉(zhuǎn)換成用于顯示的 viewModel,然后將 viewModel 傳遞回 ViewController 以顯示給用戶。
保存對(duì) ViewController(輸出)的弱引用。

Worker(工作器)

當(dāng)所有的業(yè)務(wù)邏輯都位于 Interactor 中時(shí),可能會(huì)導(dǎo)致Interactor是一個(gè)非常大的類。 為了防止這種情況,一個(gè)Interactor 可以使用多個(gè) WorkerWorkerInteractor 的助手,可以幫助接收數(shù)據(jù)。

  • Worker是處理不同底層操作的抽象,比如從網(wǎng)絡(luò)/數(shù)據(jù)庫(kù)獲取信息、上傳/下載照片、喜歡/關(guān)注用戶等。
  • 應(yīng)遵循單一職責(zé)原則(一個(gè) Interactor 可能包含許多具有不同職責(zé)的 Worker)。
  • Worker必須是通用的,這樣就可以被多個(gè) Interactor 使用。

注:如果你使用第三方SDK,比如使用 AFNetworking 做網(wǎng)絡(luò)請(qǐng)求,而網(wǎng)絡(luò)請(qǐng)求是在Worker里面做的,那么只需在 Worker 中引入AFNetworking。

Router(路由器)

有可能存在當(dāng)前場(chǎng)景的 ViewController 將展示另一個(gè) ViewController 的情況。 在 Clean Swift中,ViewController 之間的導(dǎo)航是由 Router 完成的。

當(dāng)屏幕或場(chǎng)景發(fā)生轉(zhuǎn)換時(shí),ViewController 需要向Interactor發(fā)起Request,然后 Interactor 需要向Presenter 進(jìn)行詢問(wèn),最終由 Presenter 來(lái)決定 ViewController 可以使用 Router 路由到哪一個(gè) ViewController。

  • RouterViewController 中提取所有的導(dǎo)航邏輯,這使得 ViewController 具有哪些導(dǎo)航選項(xiàng)變得一目了然。
  • 保存對(duì)源ViewController 的弱引用。
Model

VIP Cycle 中,每個(gè)類在向該循環(huán)中的其他類進(jìn)行請(qǐng)求動(dòng)作時(shí)都會(huì)創(chuàng)建一個(gè)數(shù)據(jù)對(duì)象。 這樣做的目的是解耦各個(gè)類。

  • 當(dāng) ViewControllerInteractor 請(qǐng)求一個(gè)動(dòng)作時(shí),ViewController 將添加一個(gè)“請(qǐng)求”對(duì)象(Request)。 該對(duì)象包含Interactor在執(zhí)行業(yè)務(wù)邏輯時(shí)需要的所有數(shù)據(jù)。
  • Interactor 將處理來(lái)自 ViewController的請(qǐng)求。 處理完成后,它將向 Presenter 返回一個(gè)“響應(yīng)”對(duì)象(Response)。
  • Presenter 將解析來(lái)自 Interactor 的 原始數(shù)據(jù),提取/轉(zhuǎn)換用于顯示的數(shù)據(jù)并封裝為 “ViewModel”對(duì)象,該對(duì)象將被發(fā)送到 ViewController。
  • 當(dāng) ViewController 接收到 ViewModel 時(shí),ViewController 只需要使用 ViewModel 中的數(shù)據(jù)更新 UI即可。

三、總結(jié)

完整模式

ViewController 在初始化完成后,在內(nèi)部創(chuàng)建 InteractorPresenter、Router實(shí)例,ViewController僅保存InteractorRouter 實(shí)例,將 Presenter 實(shí)例傳遞給 Interactor 來(lái)保存,并將ViewController作為弱引用傳遞給 PresenterRouter(防止循環(huán)引用)。

優(yōu)點(diǎn)
  • 易于維護(hù)、擴(kuò)展和bug fix。因?yàn)槟憧梢源_切地知道哪個(gè)邏輯位于哪個(gè)類中。
  • 很好地執(zhí)行了單一職責(zé)原則。
  • 很好地使用 Worker 構(gòu)建可重用的組件。
  • 由于使用協(xié)議來(lái)進(jìn)行類之間的解耦,因此當(dāng)需要替換一個(gè)類時(shí),只需要讓新的類遵從某個(gè)協(xié)議,而無(wú)需修改其他類的代碼。
  • 方便進(jìn)行單元測(cè)試,并容易達(dá)到很高的代碼覆蓋率。
缺點(diǎn)
  • 許多協(xié)議的命名和職責(zé)復(fù)雜,起初可能會(huì)混淆協(xié)議在哪里定義。
  • 很難保持 ViewControllerPresenter 之間的完全分離。因?yàn)橛袝r(shí) Presenter 只是調(diào)用 ViewController的方法而不是準(zhǔn)備UI顯示用的數(shù)據(jù),因此它看起來(lái)沒(méi)用,只是為了要遵守樣板代碼而不得不這樣做。
總結(jié)
  • Clean Swift 不是最容易維護(hù)的,但可能是避免耦合并能夠保持高代碼覆蓋率的最佳方法。
  • VIP Cycle 使用中等數(shù)量的樣板代碼強(qiáng)制執(zhí)行嚴(yán)格的命名約定和類職責(zé)。

參考資料

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

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

  • 您的客戶要求估算以修復(fù)錯(cuò)誤。你告訴他也許幾個(gè)小時(shí)。但是你內(nèi)心深處知道你只是不確定。你只需要給出一個(gè)數(shù)字。 如果它花...
    荒年ing閱讀 1,037評(píng)論 0 1
  • 前言 對(duì)于一個(gè)設(shè)計(jì)比較簡(jiǎn)單的app來(lái)說(shuō),這個(gè)app對(duì)應(yīng)只有幾個(gè)頁(yè)面,功能也不是很多的時(shí)候,這個(gè)app總的代碼量比較...
    磚頭很燙手閱讀 2,985評(píng)論 4 10
  • 原創(chuàng):知識(shí)探索型文章創(chuàng)作不易,請(qǐng)珍惜,之后會(huì)持續(xù)更新,不斷完善個(gè)人比較喜歡做筆記和寫總結(jié),畢竟好記性不如爛筆頭哈哈...
    時(shí)光啊混蛋_97boy閱讀 1,101評(píng)論 0 1
  • 本文翻譯自 Clean SwiftGitHub Demo 過(guò)去兩年,有許多關(guān)于 VIPER 的文章,這是一種在iO...
    plantseeds閱讀 1,709評(píng)論 0 1
  • 原創(chuàng)作者:Piyush Sharma原文鏈接:https://medium.com/@piyush.dez/ios...
    Grabin閱讀 616評(píng)論 0 0

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