一個簡單登錄示例的MVC和MVP實現

xbeB5.jpg

做者:長劍廢水(博客) 登陸示例:MVC 自上篇《iOS基於MVC的項目重構》總結以後,我又思考了下面這個問題:在UIKit自身的設計中UIViewController是被當作C仍是V呢? 例如咱們點擊View上某個Button時,可能會使用調用self.navigationController的pushViewController:animated:方法來跳轉到一個新的界面。 在這個場景中,點擊事件經過View傳遞到UIViewController,而後跳轉到一個新的MVC。事件的邏輯處理是在UIViewController中完成的,事件的處理者是self(一個UIViewController),可見在UIKit中UIViewController是被視爲Controller的。 那麼第二個問題來了,若是須要在一個UIViewController中實現很複雜的View結構或者subViews之間的動畫邏輯,那麼如何合理設計UIViewController和UIView二者之間的關係呢? 在上文中說過,個人想法是經過給每個UIViewController設計一個對應的XXXContainerView,經過這樣的方式來強行分離V和C,避免因爲V太複雜時出現MassiveViewController。但這樣同時也帶來了一個壞處:沒法像在UIViewController自帶的view裏添加控件同樣,能夠將控件的響應方法直接綁定到UIViewController的.m文件中,也沒法享受相似viewDidDisappear:生命週期方法帶來的便利了。 固然,對於有必定MVC經驗的開發者,也能夠經過相似下面的代碼來簡化XXXContainerView這一層: 1 2 3 [self.view addSubview:self.topView]; [self.view addSubview:self.midView]; [self.view addSubview:self.bottomView]; 雖然任何Demo都不可能模擬出實際項目中遇到的問題,但經過不一樣橫向對比仍是很容易看出不一樣架構的區別所在。接下來,我將以我目前對MVC的理解,給出一個簡單的登陸示例Demo(Demo地址)。 Demo十分簡單,這裏僅作簡單說明: LoginContainerView:負責建立用戶所能看到的界面,以及將向Controller中傳遞登陸事件和登陸參數。 LoginModel:提供接口完成具體的登陸業務,Demo中省略了網絡層以及存儲層。 LoginController:負責建立LoginContainerView,以及當監聽到登陸事件時,調用LoginModel中的登陸業務方法。 因爲僅爲了明確MVC的結構,因此Demo中對不少實際項目設計到的業務沒有具體處理,好比網絡請求(Demo中經過本地進行了模擬),數據持久化,以及登陸成功後rootViewController的切換。 這裏有一點值得談論的時,對用戶輸入數據的校驗應該放在哪一層來完成呢?爲了簡化調用,Demo中是直接放在View層來進行判斷的。固然,好像放在任何一層都有道理。 上面也提到過,MVC的一個複雜點在於,當View結構複雜以後,若是一個UIViewcontroller來管理多個的複雜的View,勢必會形成View層和Controller層的交互變得複雜,並隨着業務增加逐漸膨脹,直至崩潰。 那麼,爲每一個單獨的View構造一個對應的Controller是否可行呢? 其實UIKit就是這麼作的,好比UINavigationController棧中的每一項,都是一個新的MVC,更具體的關於多重MVC的介紹能夠參見斯坦福大學公開課:iOS 8開發-多重 MVC。 可是實際開發中對於咱們自定義的繼承自UIView的類,好像咱們都並無對其建立一個Controller的習慣—除非你願意加班來完成這些額外的代碼。蘋果也沒有強制推薦這麼作—不然,只要設置不能單首創建UIView,只有經過UIViewController才能建立UIView就能夠了。 接下來,一樣對這個登陸示例,我會再給出一個MVP的例子。經過兩者橫向對比,二者的差別會很明顯的體現出來。 登陸示例:MVP 在上文MVC登陸示例中提到了一點,在一個Controller管理多個複雜View的場景時,C和V之間的事件以及參數傳遞會變得很不暢,而實際開發中咱們也沒有爲每一個繼承自View建立對應Controller的開發習慣。 爲何會出現這麼彆扭的狀況呢?《iOS基於MVC的項目重構》總結中我簡單提到過MVC和MVP的差別: 個人理解是,MVP是用戶視角:所見即View。MVC則是程序員視角:I control everyone。 在羣裏討論的時候有人問我這句話如何解釋,在這裏我詳細說明一下。 MVC中的C能夠比喻爲一個大管家,家裏的每一個成員(View)須要就餐時,會將每一個人的口味偏好告知給管家(Controller),管家將這些信息告知廚房(Model),廚房作好後上菜開飯。 MVP中的P則能夠比喻爲一個私人祕書,你要吃什麼直接跟祕書(Presenter)說就行了,只要祕書(Presenter)擁有調用廚房(Model)的權限便可。 一句話總結,C是家族大管家,P是貼身小祕書。 可能這裏解釋的仍是不太清楚,仍是直接用代碼來講明吧。 MVP登陸示例Demo Demo的簡單說明以下: View層:LoginViewController負責建立UI,響應交互。當有交互事件觸發時,調用本身的preseter的對應方法處理。 Presenter層:LoginPresenter,是LoginViewController的貼身祕書,負責具體處理事件交互,並將處理結果報告給LoginViewController。 Model層:LoginModel,完成登陸業務邏輯。 對比MVC,之前View的事件通知給Controller可能須要使用block,delegate,View結構層級複雜的話可能還須要使用通知等等。還會多個View共用一個Controller的狀況:Controller拿到Model的返回後,須要將返回值交給View並逐級傳遞下去完成展現。 而在MVP中,每一個View都會有一個貼身Presenter來處理交互,這樣就將本來MVC中的多View共用Controller的場景進行了拆分,這樣避免了出現跨層傳值的狀況。(示例涉及到一個界面,由於沒有模擬這種狀況) 架構設計並非爲了給開發者增長麻煩,而是在開發及維護的大層面上給開發者減小麻煩。 可能有的開發者會說,這麼簡單的一個登錄隨便寫寫不就完了,所謂」專家」就會把簡單問題複雜化。可是,若是每一個人都隨便寫寫的話, 「There are a thousand Hamlets in a thousand people’s eyes.」 莎士比亞的這句話在程序開發中絕對是禁忌,沒有人願意維護一段代碼的時候還要穿越時空去復現你開發時的思惟。程序員

相關文章
相關標籤/搜索