UIViewController和UIViewController之間的交互

轉載時請註明出處和作者聯繫方式

文章出處:http://blog.csdn.net/jack0106 

作者聯繫方式:馮牮 [email protected]


       UIViewController之間,是否需要交互,怎樣交互?這個問題困擾我一段時間了,憑空的去想象,其實很難想明白,尤其是在短時間內。最好的辦法,還是在持久的編碼/讀代碼的過程中,根據不同的使用場合及使用需求,來學習體會。


       順便還想說一句,圖形界面編程,最基本的編程思路和方法都是類似的,如果你熟悉不止一種圖形SDK,你就會發現其實它們都是觸類旁通的。最近我就遊走於cocoa和qml之間,再加上之前qtwidget、gtk、clutter的編程經驗,我發現使用這些不同的sdk,對於我個人的編程技能的增長,很好的起到了互補的作用。


       假設使用UINavigationController進行導航,有兩層界面結構,都使用自定義UIViewController的子類,分別爲level1ViewController和level2ViewController。

 

1 單向交互。

       第一級level1ViewController負責創建第二級level2ViewController,並且設置level2ViewController相關的屬性,然後push level2ViewController。僞代碼如下:

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


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

 

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

 

2 雙向交互,共享數據

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

[[shareData alloc] init];
…
[[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後,僞代碼如下:

[[shareData alloc] init];
[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嚴格對應,“場景”是更抽象化的內容,更符合人類的直觀感覺,而controll/頂層view是更工程化的概念,更精確。在用戶體驗設計中,有些不同的場景,在邏輯上其實可以屬於同一個controll或頂層view。這個隨着經驗的增長,體會才能夠更加的深刻。

 

        關於用戶體驗設計中的場景,推薦一片文章,可以看看其中舉的一些例子,找找感覺。

        不拘規範的iPhone優秀應用設計細節     http://ucdchina.com/snap/10799


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章