代理設(shè)計模式溫顧

前言

通過閱讀了劉小壯大神的博客你真的了解iOS代理設(shè)計模式嗎?對以前模糊的代理設(shè)計模式有了新的認識。略做記錄,供自己記憶。

iOS中消息傳遞的方式

  • 通知:由通知中心發(fā)送通知給通知的接受者,是一種一對多的消息傳遞方式
  • 代理:代理設(shè)計模式由代理、協(xié)議、委托三部分組成
  • 閉包:iOS4.0以后引入,block實質(zhì)是存儲了一段代碼塊內(nèi)存的指針
  • target action:通過將對象傳遞到另一個類中,在另一個類中將該對象當(dāng)做target的方式,來調(diào)用該對象方法,從內(nèi)存角度來說和代理類似
  • KVO:通過監(jiān)聽某一個實例的某一個屬性值變化,當(dāng)那個屬性的值發(fā)送變化時,會調(diào)用KVO的回調(diào)方法

代理的基本使用

代理主要由三個部分組成

  • 協(xié)議:協(xié)議就是填寫那些需要代理方執(zhí)行的方法
  • 委托:指定遵循協(xié)議的代理去完成方法
  • 代理:完成委托方委托的方法

在通常情況下我們都會吧協(xié)議寫在委托方的文件下,但是當(dāng)多個類需要用到同一個協(xié)議時,我們可以創(chuàng)建一個協(xié)議文件,protocol也是可以被繼承的(自己這只菜鳥不知道!)例如我們常用的UITableView,由于繼承自UIScrollView的緣故,所以也將UIScrollViewDelegate繼承了過來,我們可以通過代理方法獲取UITableView偏移量等狀態(tài)參數(shù)。iOS中對象不支持多繼承,但是協(xié)議可以多繼承

代理的原理

以前在給代理設(shè)置屬性的時候一直沿襲網(wǎng)上的assign寫法,也不知道為什么這么寫,但是看了大神的文章才明其緣由。原來安全的寫法應(yīng)該是用weak,在委托釋放的時候,代理對象也會跟著釋放,從而不會造成循環(huán)引用的問題,而且也不會向野指針發(fā)送消息,從而引起程序奔潰。
 代理的本質(zhì)就是代理對象內(nèi)存的傳遞和操作,我們在委托類設(shè)置代理對象后,實際上只是用一個id類型的指針將代理對象進行了一個弱引用。委托方讓代理方執(zhí)行操作,實際上是在委托類中向這個id類型指針指向的對象發(fā)送消息,而這個id類型指針指向的對象,就是代理對象。
 其實委托方的代理屬性本質(zhì)上就是代理對象自身,設(shè)置委托代理就是代理屬性指針指向代理對象,相當(dāng)于代理對象只是在委托方中調(diào)用自己的方法,如果方法沒有實現(xiàn)就會導(dǎo)致崩潰。從崩潰的信息上來看,就可以看出來是代理方?jīng)]有實現(xiàn)協(xié)議中的方法導(dǎo)致的崩潰。

利用代理對控制器瘦身

優(yōu)化我們經(jīng)常使用的UITableView,核心思想就是通過繼承其代理,然后將原控制器的代理對象的方法全部挪到新的代理對象中去,好像說的不是太清楚。。。這樣就可以新建一個代理對象類,然后繼承UItabelView的delegate和datasource,然后在這個代理文件中執(zhí)行UItabelView的代理方法,這樣就可以把很多的代碼方法到這個新的代理對象中,大大減輕主控制器中的代碼了。

知識補充

本渣渣完全不知道的東西↓
在iOS2.0之前還沒有引入@Protocol正式協(xié)議之前,實現(xiàn)協(xié)議的功能主要是通過給NSObject添加Category的方式。這種通過Category的方式,相對于iOS2.0之后引入的@Protocol,就叫做非正式協(xié)議。

正如上面所說的,非正式協(xié)議一般都是以NSObject的Category的方式存在的。由于是對NSObject進行的Category,所以所有基于NSObject的子類,都接受了所定義的非正式協(xié)議。對于@Protocol來說編譯器會在編譯期檢查語法錯誤,而非正式協(xié)議則不會檢查是否實現(xiàn)。

非正式協(xié)議中沒有@Protocol的@optional和@required之分,和@Protocol一樣在調(diào)用的時候,需要進行判斷方法是否實現(xiàn)。

在iOS早期也使用了大量非正式協(xié)議,例如CALayerDelegate就是非正式協(xié)議的一種實現(xiàn),非正式協(xié)議本質(zhì)上就是Category。

關(guān)于代理和block的區(qū)別

對于這個代理和block,我更加喜歡使用block,因為本渣渣懶哈,block使用比較簡單。其實不然,很多地方代理有很大的優(yōu)勢,當(dāng)然block也一樣。

  • 當(dāng)需要傳遞多個參數(shù)的時候,block看起來會非常的臃腫,而且條例不清晰,但是用代理就非常合適了,看起來也非常的清晰明了。
  • 代理對象只能擁有一個,如果你對一個委托方的代理對象重復(fù)賦值,那代理對象只會是最后一個賦值的對象,其實就是屬性的重新賦值了。如果想要委托對象回調(diào)多個代理對象應(yīng)該用block。(這里主要是針對于對象內(nèi)部屬性不會對block進行引用的情況下,否則再調(diào)用同一個方法也會造成重新賦值問題)上面這句話我也不是很清楚,但是博主在最后面寫的應(yīng)該是block可以在多處調(diào)用,就是說,可以在多住調(diào)用這個block內(nèi)部的代碼塊吧。
  • 單例對象不要使用代理。
  • 無論是代理還是block在使用的時候都要先驗證其是否實現(xiàn)。
  • 代理更加面向過程,但是block更加面向結(jié)果。如果當(dāng)你的程序希望更注重過程時,可以使用代理。當(dāng)你覺得結(jié)果更加重要的時候,你可以使用block。
  • 從性能上講,block更加耗性能一些,應(yīng)為block會涉及沖棧區(qū)先堆區(qū)拷貝,所以在時間和空間上的消耗都是大于代理代碼。而代理只是定義了一個方法的列表。在自己的協(xié)議方法列表中添加了一個節(jié)點。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容