我對擴展方法的糟糕體驗是my March 2016 talk at iOSoHo in New York的第一個也是最重要的部分的基礎。我所說的關於擴展的大部分內容並不在幻燈片中。擴展方法有以下幾個問題:
- 您只能有一個模型到視圖的映射(沒有另一箇中間層來提供邏輯協調擴展屬性)。這極大地損害了視圖的可重用性。
- 關於第1點,即使你身邊這個座標,你可能會得到碰撞,如果你使用的型號很多地方,例如
name
再後來加入firstNameOnly
等絕對是一個模型只能不斷遵循協議的一種方式,如果你想要這樣做。
- 提供了替代模型的虛擬值,做汽車設計,調試,故障情況等,幾乎是不可能的。您可能會發現自己正在爲此編寫一個結構 - 這是一個ViewModel。
- 如果您有一個視圖需要多個模型來填充模型,或需要模型外部的信息,則視圖模型會簡化它們之間的協調。
通過ViewModel,這些重要情況變得微不足道。 (在演講中,我所說的「命令」,因爲他們完全匹配的四種設計模式定義命令剛; 設計模式筆記也被稱爲行動,即UIAlertAction)
我採取的做法是一個「 ViewModel「應該是輕量級的,不可變的,並且通過單向數據流分佈。他們已經存儲了屬性,但是這只是爲了移動數據,虛擬機本身是不可變的,一次性的。這與2017年3月iOSoHo上的Facebook提到的方法類似,但我認爲他們不稱他們爲視圖模型,只是輕量級對象。你可以在那裏放置更復雜的邏輯,但最好是最多可以調用其他地方處理的更復雜的邏輯。
另外一個我認爲是關鍵的問題,我的規則是,無論您稱之爲「ViewModel」,都不應該有程序員無法編寫線框的屬性。因此,一個var dateString : String
不var date : NSDate
。這是我在幻燈片中的厚臉皮術語,即「Modal Object Attribute Transformer」。但是有一點很重要:城堡需要能夠吊起吊橋並在圍困時進行;當網絡中斷(或還不存在)時,視圖需要完全正常運行。如果您的觀點能夠做到這一點,您將在許多場景中擁有更容易的時間。
就在幾個星期前,我採用了這種方法,並且能夠在大約4天內創建多個複雜的屏幕,僅從設計開始工作,最終將由來自網絡的數據填充,但目前沒有任何模型或網絡層。當數據層準備就緒後,我可以簡單地編寫一些創建方法init(with: Model)
或更好static func withModelforCase1(_ model: Model) -> ViewModel
並在創建方法中寫入映射,然後在連接模型時,用這些創建方法替換static func debugCase1() -> ViewModel
。隨着模型的發展,編譯器會在這裏拋出錯誤,只會在這裏拋出錯誤;隨着視圖的發展,調整ViewModel,再次,編譯器會在這裏拋出錯誤,而且只會在這裏拋出錯誤。沒有其他代碼需要被觸及。
擴展在開始時看起來非常優雅,但實際上在模型和視圖之間創建了緊密耦合。某種ViewModel方法是一個強大的系統,可滿足現代iOS應用程序的需求 - 以及現代iOS應用程序開發。
大多數情況下,我的@import UIKit幾乎總是處於「ViewModel」擴展模式。 – Mugunth
http://www.sprynthesis.com/2014/12/06/reactivecocoa-mvvm-introduction/ –
究竟爲什麼要這麼做?我注意到NSManagedObject的子類是以相同的方式生成的,它是空的,但擴展中的屬性。 ViewModel應該是objc中的結構體或NSObject。 –