2017-06-23 19 views
2

因爲Swift/Objective-C支持編寫擴展,所以我在模型的擴展類中編寫「ViewModel」屬性,並在通常使用ViewModel的地方使用此擴展。爲什麼在iOS中使用View Model(MVVM)?

我知道分機不能有存儲性能。但是大多數MVVM體系結構不推薦ViewModel中存儲的屬性(除了那些用於緩存的屬性)。

我與維護單獨的視圖模型對象主要麻煩與模型得到它同步。是的,有很多第三方框架可以幫助使用反應式編程技術進行同步。但是,對於什麼可以解決,通過簡單地使用擴展,爲什麼使用一個沉重的框架實現相同?

我沒有擊中基於MVVM架構擴展我的一個路障。你們有沒有人嘗試過這種方式,並轉而採用響應式編程架構?

+0

大多數情況下,我的@import UIKit幾乎總是處於「ViewModel」擴展模式。 – Mugunth

+0

http://www.sprynthesis.com/2014/12/06/reactivecocoa-mvvm-introduction/ –

+0

究竟爲什麼要這麼做?我注意到NSManagedObject的子類是以相同的方式生成的,它是空的,但擴展中的屬性。 ViewModel應該是objc中的結構體或NSObject。 –

回答

2

我對擴展方法的糟糕體驗是my March 2016 talk at iOSoHo in New York的第一個也是最重要的部分的基礎。我所說的關於擴展的大部分內容並不在幻燈片中。擴展方法有以下幾個問題:

  1. 您只能有一個模型到視圖的映射(沒有另一箇中間層來提供邏輯協調擴展屬性)。這極大地損害了視圖的可重用性。
  2. 關於第1點,即使你身邊這個座標,你可能會得到碰撞,如果你使用的型號很多地方,例如name再後來加入firstNameOnly等絕對是一個模型只能不斷遵循協議的一種方式,如果你想要這樣做。
  3. 提供了替代模型的虛擬值,做汽車設計,調試,故障情況等,幾乎是不可能的。您可能會發現自己正在爲此編寫一個結構 - 這是一個ViewModel。
  4. 如果您有一個視圖需要多個模型來填充模型,或需要模型外部的信息,則視圖模型會簡化它們之間的協調。

通過ViewModel,這些重要情況變得微不足道。 (在演講中,我所說的「命令」,因爲他們完全匹配的四種設計模式定義命令剛; 設計模式筆記也被稱爲行動,即UIAlertAction)

我採取的做法是一個「 ViewModel「應該是輕量級的,不可變的,並且通過單向數據流分佈。他們已經存儲了屬性,但是這只是爲了移動數據,虛擬機本身是不可變的,一次性的。這與2017年3月iOSoHo上的Facebook提到的方法類似,但我認爲他們不稱他們爲視圖模型,只是輕量級對象。你可以在那裏放置更復雜的邏輯,但最好是最多可以調用其他地方處理的更復雜的邏輯。

另外一個我認爲是關鍵的問題,我的規則是,無論您稱之爲「ViewModel」,都不應該有程序員無法編寫線框的屬性。因此,一個var dateString : Stringvar date : NSDate。這是我在幻燈片中的厚臉皮術語,即「Modal Object Attribute Transformer」。但是有一點很重要:城堡需要能夠吊起吊橋並在圍困時進行;當網絡中斷(或還不存在)時,視圖需要完全正常運行。如果您的觀點能夠做到這一點,您將在許多場景中擁有更容易的時間。

就在幾個星期前,我採用了這種方法,並且能夠在大約4天內創建多個複雜的屏幕,僅從設計開始工作,最終將由來自網絡的數據填充,但目前沒有任何模型或網絡層。當數據層準備就緒後,我可以簡單地編寫一些創建方法init(with: Model)或更好static func withModelforCase1(_ model: Model) -> ViewModel並在創建方法中寫入映射,然後在連接模型時,用這些創建方法替換static func debugCase1() -> ViewModel。隨着模型的發展,編譯器會在這裏拋出錯誤,只會在這裏拋出錯誤;隨着視圖的發展,調整ViewModel,再次,編譯器會在這裏拋出錯誤,而且只會在這裏拋出錯誤。沒有其他代碼需要被觸及。

擴展在開始時看起來非常優雅,但實際上在模型和視圖之間創建了緊密耦合。某種ViewModel方法是一個強大的系統,可滿足現代iOS應用程序的需求 - 以及現代iOS應用程序開發。

+0

可能是最接近其他答案的答案。 – Mugunth

+0

@Mugunth是的架構問題總是成爲臨界意見,但可以通過事實考慮得到通知,例如在第2點中,模型只能以一種方式符合協議(注意這一點 - 我意識到了這是困難的方式)。沒有試圖說服你ViewModels是「更好」,只是回答你可能使用它們而不是擴展的「爲什麼」。我認爲很多人都有一個很好的問題。感謝接受。 –

1

ViewModel應該是從建築POV不同的實體,而不是從代碼佈置POV。您對MVVM進行模型擴展的方法會使模型知道太多並且違反了SRP,例如,如果模型具有某個日期屬性,則視圖模型通常會用於使用當前語言環境對其進行格式設置。如果Model是數據存儲,它應該只包含相關的數據結構並且不包含任何方法。如果Model是服務(例如網絡客戶端),它應該只包含相關的方法,只需要最少的數據轉換(例如json to struct)。

而且在我的實踐我有時有一個以上的虛擬機的單一模式。如果說,我有一個User模型firstNamelastNameemail屬性,我可能需要fullName屬性爲(以UserCellViewModel實現)錶行中顯示出來,但在詳細視圖顯示用戶信息時,所有三個屬性(UserDetailViewModel實施)。通過對模型的擴展,所有四個屬性(fullName在擴展中實現)都可以在所有情況下訪問。使控制器消耗ViewModel儘可能少知道是一件好事(需要引用)。這可以在Objective-C中實現,其中你的擴展可以擁有自己的頭文件/接口文件,但是你在Swift中沒有這樣做。 MVVM 視圖模型的

+0

爲「隱藏」屬性,我經常使用'公共私營(套)'聲明。 – Mugunth

+1

'公私臺(套)'只是隱藏二傳手,而不是物業本身。 OOP和封裝是基於需要知道的基礎。因此,它是更好地隱藏它完全,而不是承諾自己不使用它時,你不需要它。) – Eimantas

2

好處是把你的驗證邏輯用戶輸入,視圖呈現邏輯,網絡請求的好地方。結果,ViewController文件變得臃腫得多。 另外,View-ViewController組件與模型完全隔離。所以在開發過程中,一個開發人員可以在屏幕的UI部分工作,另一個開發人員可以獨立地併發地處理屏幕的邏輯。 很容易重新設計用戶界面而不會與模型邏輯混淆,因爲它們都是完全隔離的。只要將適當的屬性鏈接到ViewModel,就可以交換視圖組件。這給了用戶界面更多的自由體驗。 對於通用應用程序,iPad和iPhone ViewController都可以與相同的ViewModel進行交互。 測試起來比較容易。開發人員可以在沒有視圖的情況下爲ViewModel和模型創建單元測試。

+0

這正是爲什麼我使用模型的擴展。有沒有一部分,這是不可行的使用擴展? – Mugunth

+0

你可以以任何方式做任何事情,如果你願意,你也可以讓你的整個應用適合AppDelegate,但這不是一個好習慣。良好的代碼遵循SOLID原則,您的解決方案不適用,尤其是SRP –

相關問題