轉(zhuǎn)載自:http://blog.csdn.net/dqjyong/article/details/7685933
在開發(fā)IOS應用的時候弓熏,我們會經(jīng)常遇到一個常見的問題:在不過分耦合的前提下恋谭,controllers[B]怎么進行通信。在IOS應用不斷的出現(xiàn)三種模式來實現(xiàn)這種通信:
1委托delegation
2通知中心Notification Center
3鍵值觀察key value observing挽鞠,KVO
因此疚颊,那為什么我們需要這些模式以及什么時候用它以及什么時候不用它狈孔。
下面完全根據(jù)我的開發(fā)經(jīng)驗來討論這三中模式。我將討論為什么我覺得某種模式要好于另外一種模式以及為什么我覺得在一定的環(huán)境下某中模式比較好材义。我給出的這些原因并不是圣經(jīng)均抽,而僅僅是個人觀點。如果你有什么不同的觀點或者還可以進行補充的地方其掂,可以聯(lián)系我油挥,一起討論。
上面的三種模式是什么款熬?
三種模式都是一個對象傳遞事件給另外一個對象深寥,并且不要他們有耦合。三種模式都是對象來通知某個事件發(fā)生了的方法贤牛,或者更準確的說惋鹅,是允許其他的對象收到這種事件的方法。這對于一個對象來說殉簸,是非常普通而且必須做的任務闰集,因為沒有通信,controllers將不能整合到整個應用中般卑。controller的另外一個目的是盡可能的自包含武鲁。
我們希望controllers以自己的方式存在,在controllers屢面上不能與其他的controllers進行耦合椭微。Controllers能夠創(chuàng)建其他的controllers而且他們之間可以自由通信洞坑,但是我們不希望controller又回接到創(chuàng)建自己的controller。如果我們耦合了他們蝇率,那么我們將不能復用他們迟杂,以及完全失去對應用中一個獨立的組件的控制。
這三種模式給controllers(也可以是其他的對象)提供通信的方法本慕。下面將描述如何在IOS應用中使用這些模式同樣需要注意的他們在其他的地方也會用到排拷,并且確實是存在。
. delegation
當我們第一次編寫IOS應用時锅尘,我們注意到不斷的在使用“delegate"监氢,并且貫穿于整個SDK。delegation模式不是IOS特有的模式藤违,而是依賴與你過去擁有的編程背景浪腐。針對它的優(yōu)勢以及為什么經(jīng)常使用到,這種模式可能不是很明顯的顿乒。
delegation的基本特征是议街,一個controller定義了一個協(xié)議(即一系列的方法定義)。該協(xié)議描述了一個delegate對象為了能夠響應一個controller的事件而必須做的事情璧榄。協(xié)議就是delegator說特漩,“如果你想作為我的delegate吧雹,那么你就必須實現(xiàn)這些方法”。實現(xiàn)這些方法就是允許controller在它的delegate能夠調(diào)用這些方法涂身,而它的delegate知道什么時候調(diào)用哪種方法雄卷。delegate可以是任何一種對象類型,因此controller不會與某種對象進行耦合蛤售,但是當該對象嘗試告訴委托事情時丁鹉,該對象能確定delegate將響應。
三者優(yōu)缺點:
delegate 的 優(yōu)勢 :
1.非常嚴格的語法悍抑。所有將聽到的事件必須是在delegate協(xié)議中有清晰的定義鳄炉。
2.如果delegate中的一個方法沒有實現(xiàn)那么就會出現(xiàn)編譯警告/錯誤
3.協(xié)議必須在controller的作用域范圍內(nèi)定義
4.在一個應用中的控制流程是可跟蹤的并且是可識別的;
5.在一個控制器中可以定義定義多個不同的協(xié)議搜骡,每個協(xié)議有不同的delegates
6.沒有第三方對象要求保持/監(jiān)視通信過程拂盯。
7.能夠接收調(diào)用的協(xié)議方法的返回值。這意味著delegate能夠提供反饋信息給controller
8.經(jīng)常被用在存在父子關系的對象之間通信记靡,例如控制器和控制器的view(自己加的理解)
缺點 :
1.需要定義很多代碼:1.協(xié)議定義谈竿;2.controller的delegate屬性;3.在delegate本身中實現(xiàn)delegate方法定義
2.在釋放代理對象時摸吠,需要小心的將delegate改為nil空凸。一旦設定失敗,那么調(diào)用釋放對象的方法將會出現(xiàn)內(nèi)存crash
3.在一個controller中有多個delegate對象寸痢,并且delegate是遵守同一個協(xié)議呀洲,但還是很難告訴多個對象同一個事件,不過有可能啼止。
4.經(jīng)常用在一對一的通信道逗。(不知道是缺點還是優(yōu)點,只能算是特點)(自己加的理解)
notification 的 優(yōu)勢 :
1.不需要編寫多少代碼献烦,實現(xiàn)比較簡單
2.對于一個發(fā)出的通知滓窍,多個對象能夠做出反應,即一對多的方式實現(xiàn)簡單
3.controller能夠傳遞context對象(dictionary)巩那,context對象攜帶了關于發(fā)送通知的自定義的信息
缺點 :
1.在編譯期不會檢查通知是否能夠被觀察者正確的處理吏夯;
2.在釋放注冊的對象時,需要在通知中心取消注冊即横;
3.在調(diào)試的時候應用的工作以及控制過程難跟蹤噪生;
4.需要第三方對象來管理controller與觀察者對象之間的聯(lián)系;
5.controller和觀察者需要提前知道通知名稱东囚、UserInfo dictionary keys杠园。如果這些沒有在工作區(qū)間定義,那么會出現(xiàn)不同步的情況;
6.通知發(fā)出后抛蚁,controller不能從觀察者獲得任何的反饋信息(相比較delegate)。
KVO 的 優(yōu)勢 :
1.能夠提供一種簡單的方法實現(xiàn)兩個對象間的同步惕橙。例如:model和view之間同步瞧甩;
2.能夠?qū)Ψ俏覀儎?chuàng)建的對象,即內(nèi)部對象的狀態(tài)改變作出響應弥鹦,而且不需要改變內(nèi)部對象(SKD對象)的實現(xiàn)肚逸;
3.能夠提供觀察的屬性的最新值以及先前值;
4.用key paths來觀察屬性彬坏,因此也可以觀察嵌套對象朦促;
5.完成了對觀察對象的抽象,因為不需要額外的代碼來允許觀察值能夠被觀察
6.可以一對多栓始。
缺點 :
1.我們觀察的屬性必須使用strings來定義务冕。因此在編譯器不會出現(xiàn)警告以及檢查;
2.對屬性重構將導致我們的觀察代碼不再可用幻赚;
3.復雜的“IF”語句要求對象正在觀察多個值禀忆。這是因為所有的觀察代碼通過一個方法來指向;
4.當釋放觀察者時不需要移除觀察者落恼。
1.? 效率 肯定是delegate比NSNotification高箩退。
delegate方法比notification更加直接,最典型的特征是佳谦,delegate方法往往需要關注返回值戴涝, 也就是delegate方法的結果。比如-windowShouldClose:钻蔑,需要關心返回的是yes還是no啥刻。所以delegate方法往往包含 should這個很傳神的詞。也就是好比你做我的delegate矢棚,我會問你我想關閉窗口你愿意嗎郑什?你需要給我一個答案,我根據(jù)你的答案來決定如何做下一 步蒲肋。相反的蘑拯,notification最大的特色就是不關心接受者的態(tài)度, 我只管把通告放出來兜粘,你接受不接受就是你的事情申窘,同時我也不關心結果。所以notification往往用did這個詞匯孔轴,比如 NSWindowDidResizeNotification剃法,那么NSWindow對象放出這個notification后就什么都不管了也不會等待接 受者的反應。
2路鹰、KVO和NSNotification的區(qū)別 :
和delegate一樣贷洲,KVO和NSNotification的作用也是類與類之間的通信收厨,與delegate不同的是1)這兩個都是負責發(fā)出通知,剩下的事情就不管了优构,所以沒有返回值诵叁;2)delegate只是一對一,而這兩個可以一對多钦椭。這兩者也有各自的特點拧额。
總結:
從上面的分析中可以看出3中設計模式都有各自的優(yōu)點和缺點。其實任何一種事物都是這樣彪腔,問題是如何在正確的時間正確的環(huán)境下選擇正確的事物侥锦。下面就講講如何發(fā)揮他們各自的優(yōu)勢,在哪種情況下使用哪種模式德挣。注意使用任何一種模式都沒有對和錯恭垦,只有更適合或者不適合。每一種模式都給對象提供一種方法來通知一個事件給其他對
象盲厌,而且前者不需要知道偵聽者署照。在這三種模式中,我認為KVO有最清晰的使用案例吗浩,而且針對某個需求有清晰的實用性建芙。而另外兩種模式有比較相似的用處,并且經(jīng)常用來給controller間進行通信懂扼。那么我們在什么情況使用其中之一呢禁荸?
根據(jù)我開發(fā)iOS應用的經(jīng)歷,我發(fā)現(xiàn)有些過分的使用通知模式阀湿。我個人不是很喜歡使用通知中心赶熟。我發(fā)現(xiàn)用通知中心很難把握應用的執(zhí)行流程。Userlnfo dictionaries的keys到處傳遞導致失去了同步陷嘴,而且在公共空間需要定義太多的常量映砖。對于一個工作于現(xiàn)有的項目的開發(fā)者來說,如果過分的使用通知中心灾挨,那么很難理解應用的流程邑退。
我覺得使用命名規(guī)則好的協(xié)議和協(xié)議方法定義對于清晰的理解controllers間的通信是很容易的。努力的定義這些協(xié)議方法將增強代碼的可讀性劳澄,以及更好的跟蹤你的app地技。代理協(xié)議發(fā)生改變以及實現(xiàn)都可通過編譯器檢查出來,如果沒有將會在開發(fā)的過程中至少會出現(xiàn)crash秒拔,而不僅僅是讓一些事情異常工作莫矗。甚至在同一事件通知多控制器的場景中,只要你的應用在controller層次有著良好的結構,消息將在該層次上傳遞作谚。該層次能夠向后傳遞直至讓所有需要知道事件的controllers都知道三娩。當然會有delegation模式不適合的例外情況出現(xiàn),而且notification可能更加有效食磕。例如:應用中所有的controller需要知道一個事件尽棕。然而這些類型的場景很少出現(xiàn)。另外一個例子是當你建立了一個架構而且需要通知該事件給正在運行中應用彬伦。
根據(jù)經(jīng)驗,如果是屬性層的時間伊诵,不管是在不需要編程的對象還是在緊緊綁定一個view對象的model對象单绑,我只使用觀察。對于其他的事件曹宴,我都會使用delegate模式搂橙。如果因為某種原因我不能使用delegate,首先我將估計我的app架構是否出現(xiàn)了嚴重的錯誤笛坦。如果沒有錯誤区转,然后才使用notification。