參考:http://www.ithao123.cn/content-8349585.html
1.Delegate(代理、委托)
代理幾乎是iOS開發中最常用的傳值方式,在項目中的AppDelegate就是使用的這種設計模式,不僅如此,還有很多原生的控件也使用的這種設計模式,比如:UITextFiled,UITableView等等。
Delegate的優點和缺陷:
優點:
1.減少代碼的耦合性,使事件監聽和事件處理相分離。
2.清晰的語法定義,減少維護成本,較強的代碼可讀性。
3.不需要創建第三方來監聽事件和傳輸數據。
4.一個控制器可以實現多個代理,滿足自定義開發需求,可選必選有較大的靈活性。
缺點:
1.實現委托的代碼過程比較繁瑣。
2.當實現跨層傳值監聽的時候將加大代碼的耦合性,并且程序的層次結構將變的混亂。
3.當對多個對象同時傳值響應的時候,委托的易用性將大大降低。
2.NotificationCenter(通知)
通知也是iOS開發中常用的一種傳值響應方法,例如在AVFoundation框架中的MPMoviePlayerController在監聽播放狀態改變,播放停止等事件時使用的也正是NotificationCenter。
NSNotification采用的單例設計模式,當給通知中心注冊一個key以后,那么無論在什么地方只要給通知中心發送一個這個key的消息,那么就實現了通信傳值,注冊的通知的對象就會調用相應的方法。
優點:
1.使用簡單,代碼精簡。
2.解決了同時向多個對象監聽相應的問題。
3.傳值方便快捷,Context自身攜帶相應的內容。
缺點:
1.使用完畢后,要時刻記得注銷通知,否則將出現不可預見的crash。
2.key不夠安全,編譯器不會監測是否被通知中心正確處理。
3.調試的時候動作的跟蹤將很難進行。
4.當使用者向通知中心發送通知的時候,并不能獲得任何反饋信息。
5.需要一個第三方的對象來做監聽者與被監聽者的中介。
3.Block(代碼塊)
Block是iOS4.0+ 和Mac OS X 10.6+ 引進的對C語言的擴展,用來實現匿名函數的特性
閉包是一個能夠訪問其他函數內部變量的函數。
官方文檔中也提到了幾種Block的使用場合。
任務完成時回調處理
消息監聽回調處理
錯誤回調處理
枚舉回調
視圖動畫、變換
排序
優點:
1.語法簡潔,實現回調不需要顯示的調用方法,代碼更為緊湊。
2.增強代碼的可讀性和可維護性。
3.配合GCD優秀的解決多線程問題。
缺點:
1.Block中得代碼將自動進行一次retain操作,容易造成內存泄露。
2.Block內默認引用為強引用,容易造成循環引用。
(二)注意事項
1.代理
在代理中調用方法的時候使用的是系統的子線程,因此,當使用Delegate進行UI操作的時候,必須調用GCD的主線程方法:
dispatch_async(dispatch_get_main_queue(), <^(void)block>),在block中寫進行的UI操作代碼。
2.通知
在通知的使用過程中Crash的原因很多情況都是注冊觀察者以后沒有及時的注銷觀察者,當然這個情況在非ARC時代比較常見,但是這并不是說在現在的ARC時代就不會出現這個問題。往往一旦出現問題就很難追查,所以還是要養成及時注銷的習慣。
由于通知的使用極其簡單,往往能夠看到很多開發人員在開發過程中濫用NSNoticationCenter的現象。導致到處都是亂七八糟的通知,代碼的可維護性和可讀性非常差,即便是使用了宏定義也不能完全避免這些問題。比如在Debug的時候,當存在多個Observe的時候,簡直就是要人命的感覺,想死的心都有了。在這方面Block和Delegate比Notification強太多了。
3.Block
當在Block中引用某個外部變量的時候,Block內部只會進行只讀拷貝,這也就意味著,即便你在使用Block之前修改了那個外部變量的值,那么在你使用的Block里面它的值依舊是最開始的那個外部變量的值。如果想要同步外部變量的值,那么就需要在block內部引用變量時,在前面加上__block關鍵字。
block本身是像對象一樣可以retain,和release。但是,block在創建的時候,它的內存是分配在棧(stack)上,而不是在堆(heap)上。他本身的作于域是屬于創建時候的作用域,一旦在創建時候的作用域外面調用block將導致程序崩潰。
(三)使用場景對比
1.回調方法
在日常的開發過程中,我們經常會遇到一些完成之后的處理問題,比如完成網路請求之后的回調,或者頁面加載完成之后的回調等。這個時候我們一般使用的是前兩者方法,即Block或者Delegate。
而在一對一傳輸回調的時候明顯Block的使用更加的簡單高效,只需要在代碼塊中執行所需要的操作即可。
在一對多的情況下,Delegate更加能夠發揮出自己的優勢。
2.跨層通信
有的時候我們需要實現在兩個毫無關聯的對象之間的通信,這個時候如果使用Block或者Delegate就勢必會增加代碼的耦合性,這樣對于代碼的結構來說是不健康的,因此這個時候使用Notification便是明智的選擇。
3.UI響應事件
用戶在與App的UI進行互動的時候,總會需要App進行交互響應,這個時候就毫無疑問的使用代理設計模式。而蘋果官方給出的建議也是可以肯定的,在Cocoa Touch框架中我們也可以在幾乎所有的UI交互控件的頭文件里看到Delegate的成員變量,也正是印證了在UI響應事件上Delegate有著絕對的優勢。
4.簡單值得傳遞
當需要進行簡單值得傳遞的時候,比如子控件傳輸給父控件所點擊的IndexPath的時候,更加適合使用Block來傳值。因為,如果只是為了傳這一個簡單的值而沒有特別的業務處理而定義一個協議,然后實現協議,設置代理再寫方法的話將十分麻煩,得不償失,這個時候簡單高效的Block就可以完美的替代Delegate完成任務了。