你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 一個簡單登陸示例的MVC和MVP實現

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

編輯:IOS開發基礎

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這一層:

[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.”

莎士比亞的這句話在程序開發中絕對是禁忌,沒有人願意維護一段代碼的時候還要穿越時空去復現你開發時的思維。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved