前言
通過閱讀了劉小壯大神的博客你真的了解iOS代理設計模式嗎窗轩?對以前模糊的代理設計模式有了新的認識嗅回。略做記錄汞贸,供自己記憶崔兴。
iOS中消息傳遞的方式
- 通知:由通知中心發(fā)送通知給通知的接受者,是一種一對多的消息傳遞方式
- 代理:代理設計模式由代理藏否、協(xié)議瓶殃、委托三部分組成
- 閉包:iOS4.0以后引入,block實質(zhì)是存儲了一段代碼塊內(nèi)存的指針
- target action:通過將對象傳遞到另一個類中副签,在另一個類中將該對象當做target的方式遥椿,來調(diào)用該對象方法,從內(nèi)存角度來說和代理類似
- KVO:通過監(jiān)聽某一個實例的某一個屬性值變化淆储,當那個屬性的值發(fā)送變化時冠场,會調(diào)用KVO的回調(diào)方法
代理的基本使用
代理主要由三個部分組成
- 協(xié)議:協(xié)議就是填寫那些需要代理方執(zhí)行的方法
- 委托:指定遵循協(xié)議的代理去完成方法
- 代理:完成委托方委托的方法
在通常情況下我們都會吧協(xié)議寫在委托方的文件下,但是當多個類需要用到同一個協(xié)議時本砰,我們可以創(chuàng)建一個協(xié)議文件碴裙,protocol也是可以被繼承的(自己這只菜鳥不知道!)例如我們常用的UITableView,由于繼承自UIScrollView的緣故舔株,所以也將UIScrollViewDelegate繼承了過來莺琳,我們可以通過代理方法獲取UITableView偏移量等狀態(tài)參數(shù)。iOS中對象不支持多繼承载慈,但是協(xié)議可以多繼承
代理的原理
以前在給代理設置屬性的時候一直沿襲網(wǎng)上的assign寫法惭等,也不知道為什么這么寫,但是看了大神的文章才明其緣由办铡。原來安全的寫法應該是用weak辞做,在委托釋放的時候,代理對象也會跟著釋放寡具,從而不會造成循環(huán)引用的問題秤茅,而且也不會向野指針發(fā)送消息,從而引起程序奔潰晒杈。
代理的本質(zhì)就是代理對象內(nèi)存的傳遞和操作嫂伞,我們在委托類設置代理對象后,實際上只是用一個id類型的指針將代理對象進行了一個弱引用拯钻。委托方讓代理方執(zhí)行操作帖努,實際上是在委托類中向這個id類型指針指向的對象發(fā)送消息,而這個id類型指針指向的對象粪般,就是代理對象拼余。
其實委托方的代理屬性本質(zhì)上就是代理對象自身,設置委托代理就是代理屬性指針指向代理對象亩歹,相當于代理對象只是在委托方中調(diào)用自己的方法匙监,如果方法沒有實現(xiàn)就會導致崩潰。從崩潰的信息上來看小作,就可以看出來是代理方?jīng)]有實現(xiàn)協(xié)議中的方法導致的崩潰亭姥。
利用代理對控制器瘦身
優(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)勢,當然block也一樣颗圣。
- 當需要傳遞多個參數(shù)的時候喳钟,block看起來會非常的臃腫,而且條例不清晰在岂,但是用代理就非常合適了奔则,看起來也非常的清晰明了。
- 代理對象只能擁有一個蔽午,如果你對一個委托方的代理對象重復賦值易茬,那代理對象只會是最后一個賦值的對象,其實就是屬性的重新賦值了祠丝。如果想要委托對象回調(diào)多個代理對象應該用block疾呻。(這里主要是針對于對象內(nèi)部屬性不會對block進行引用的情況下,否則再調(diào)用同一個方法也會造成重新賦值問題)上面這句話我也不是很清楚写半,但是博主在最后面寫的應該是block可以在多處調(diào)用岸蜗,就是說,可以在多住調(diào)用這個block內(nèi)部的代碼塊吧叠蝇。
- 單例對象不要使用代理璃岳。
- 無論是代理還是block在使用的時候都要先驗證其是否實現(xiàn)年缎。
- 代理更加面向過程,但是block更加面向結(jié)果铃慷。如果當你的程序希望更注重過程時单芜,可以使用代理。當你覺得結(jié)果更加重要的時候犁柜,你可以使用block洲鸠。
- 從性能上講,block更加耗性能一些馋缅,應為block會涉及沖棧區(qū)先堆區(qū)拷貝扒腕,所以在時間和空間上的消耗都是大于代理代碼。而代理只是定義了一個方法的列表萤悴。在自己的協(xié)議方法列表中添加了一個節(jié)點瘾腰。