在兩個ViewController之間通信的方式(轉帖整理)

一般方法

1)採用代理模式 子viewController設計代理協議,定義協議接口,父viewController 實現協議接口,實現子viewController 退出時將相關數據更新到父視圖。 常用程度 ***** 五星

2)採用ios的消息機制 父viewcontroller註冊消息,子viewcontroller發送消息,觸發父viewcontroller的消息處理。 常用程度 **** 四星

3)採用database做爲數據中間的存儲媒介,子viewcontroller將狀態數據存入DB,父viewcontroller從DB獲取數據更新view。 常用程度 * 一星

4)採用ios的NSDefault 存儲傳遞的參數。 常用程度 ** 二星

5)通過AppDelegate 中定義全局變量(或者單例)實現中間數據的存儲。 常用程度 *** 三星

 

1.單向交互

第一級level1ViewController負責創建第二級level2ViewController,並且設置level2ViewController相關的屬性,然後pushlevel2ViewController。這是最常用的方式。
僞代碼

level2ViewController = [[level2ViewController alloc] init];     
[level2ViewController setProp_1];  
[level2ViewController setProp_2];  
[level2ViewController setProp_3];  
[level1ViewController. navigationController pushViewController:level2ViewController];  
[level2ViewController release];

當然還有一種方式是在創建level2ViewController 實例的時候順便把參數也傳了,比較適用於單一參數。如果是多個參數的話,可以用一個Dictionary作爲參數的容器。

[[level2ViewController alloc] initWithParam:param]

這種情況下,從level1ViewController的角度來看,它只需要初始化level2ViewController,設置它的一些屬性,調用push,然後就什麼都不用管了。從level2ViewController的角度來看,當它被push後,在它的生命期內,都不會影響level1ViewController,不需要調用level1ViewController的函數,也沒有事件需要通知level1ViewController。

這是最簡單的使用情形,也是最理想化的。在項目設計階段,應該儘量把代碼設計成這種結構(僅僅是儘量,並不是必須。而且,也並不是所有的使用場景都都可以設計成這樣的結構,畢竟這個太理想化了)。

2.雙向交互

level1ViewController和level2ViewController使用共同的一個數據shareData(一定要理解這裏“共同”的含義—-兩個controller共享同一個數據,並且都有可能進行讀寫操作,尤其是寫操作。如果level2ViewController只對數據進行讀操作,那其實就跟前面1中的情形是一致的)。第一級level1ViewController負責創建第二級level2ViewController,並且設置level2ViewController相關的屬性,同時還要把shareData傳遞給level2ViewController,然後pushlevel2ViewController。僞代碼如下:

[[level2ViewController alloc] init];  

[level2ViewController setProp_1];  
[level2ViewController setProp_2];  
[level2ViewController setData: shareData];  

[level1ViewController. navigationController pushViewController:level2ViewController];  
[level2ViewController release];

和前一種情形的區別是,在level2ViewController的生命期內,它可能會對shareData進行寫操作,當發生這種寫操作的時候,需要讓level1ViewController知道這種變化,並且作出對應的處理。

這個時候,比較容易想到的一種解決辦法是使用Delegate,當level2ViewController寫操作shareData時,通過Delegate機制通知level1ViewController,給予level1ViewController一個機會作出正確的響應。(常用方法)

這種辦法雖然可行,但並不是首選,在面向對象編程中,經常會提到“解耦”,這裏我們就要想辦法讓這兩個controller不要聯繫的這麼緊密。那麼怎麼辦呢?

就是使用MVC模式(UIViewController本身就是MVC中的C)。這個時候,shareData就不應該再是一個普通的數據,而應該封裝成model,當model中的數據發生了改變的時候,會發出通知告訴C(和/或V)。這樣的話,兩個controller之間就比較鬆散了。引入dataModel後,僞代碼如下:

[dataModel alloc] initWithData: shareData];
[[level2ViewController alloc] init];

[level2ViewController setProp_1];
[level2ViewController setProp_2];
[level2ViewController setModel: dataModel];

[level1ViewController. navigationController pushViewController:level2ViewController];
[level2ViewController release];

當level2ViewController修改shareData後,不需要負責通知level1ViewController。shareData會負責通知它的controller。

3. 雙向交互,逆向消息傳遞

這時,基本操作都還是前面描述的1或2中的情形,區別點在於,在level2ViewController的生命期內,發生了某個事件,需要讓level1ViewController知道這個事件,並且作出對應的處理。

這個時候,就只能用Delegate了。當level2ViewController發生某個事件時,通過Delegate機制通知level1ViewController,給與level1ViewController一個機會作出正確的響應。

但是!一定要謹慎使用這種方案。如果發現代碼中需要用到這種結構,首先應該重新審視項目的架構,看能不能用前面兩種方案來處理,可能需要做一定的代碼重構。當前面的方案實在是無能爲力的時候,才考慮使用此方案。而且,儘量讓這種逆向的消息傳遞更簡單,消息事件不要太多。

4.雙向交互,大量逆向消息傳遞

這種情形和前面的3是一樣的,但是level2ViewController和level1ViewController之間的消息傳遞更復雜。

這個時候,同樣,要審視代碼的結構是否合理。而且很大的可能性是設計不合理,應該考慮把level2ViewController中管理的UIView遷移到level1ViewController中,把controller之間的交互,變成controller內部的view之間的交互,讓level1ViewController的內部聚合的更緊密一些,對外部,level1ViewController則表現的更鬆散。例如,UIAlertView或UIActionSheet,都是UIView的子類。(此處並不絕對,在有些sdk中,類似於UIAlertView或UIActionSheet的組件,它的使用情形,是符合前面3中的描述的,因爲這兩種組件的行爲模式,是有規律性的,可以很方便的複用,舉個例子,桌面編程環境中,文件選擇器這種組件,通常就是一個頂層window)

最後還要補充說明一些內容。

Cocoa是比較嚴格的執行了MVC設計模式,其中的UIViewController,可以看成是某種使用場合下,一些內在聯繫很緊密、並且協同工作的UIView的一個頂層管理容器。

在其他的sdk中,不一定有嚴格的controller,很有可能只有M和V(C的功能在V內實現),甚至只有V(簡單的使用場景,就可以不區分M和C,全在V內管理)。這個時候,就有頂層View的概念(有很多種叫法,比如page、window,或者直接使用abstractWidget),這種邏輯概念上的頂層View,在設計的時候,同樣需要考慮它們之間的交互,前面描述的這些情形,同樣可以套用。

在用戶體驗的角度來看,controll或者頂層view,通常被成爲“場景”,場景之間是否需要交互,前面的描述,也有一定的參考價值。

但是場景的概念並非總和controll或頂層view嚴格對應,“場景”是更抽象化的內容,更符合人類的直觀感覺,而controller頂層view是更工程化的概念,更精確。在用戶體驗設計中,有些不同的場景,在邏輯上其實可以屬於同一個controller.

發佈了35 篇原創文章 · 獲贊 1 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章