實(shí)現(xiàn)解釋下這個(gè)代理實(shí)現(xiàn)的一對(duì)多的代理模式大概設(shè)想,主要在開發(fā)中,經(jīng)常會(huì)遇到一種情況,那就是某個(gè)頁(yè)面或者方法中進(jìn)行了某種操作后,需要通知整個(gè)APP,不管是在哪個(gè)界面,只要接受到通知就做相應(yīng)的處理,比如說網(wǎng)絡(luò)波動(dòng)檢測(cè)、電池電量檢測(cè)、用戶切換前后臺(tái)等等情況。一般我們都是通過分類添加方法,然后在做擴(kuò)展,但是又想要達(dá)到不同類或者不同對(duì)象做不同的操作,所以寫起來(lái)比較麻煩。所以我設(shè)想并設(shè)計(jì)了一個(gè)代理模式并且能夠?qū)崿F(xiàn)一對(duì)多的通知,而且當(dāng)我不想使用的時(shí)候直接調(diào)用移除,頁(yè)面不再遵守代理,而且不用管理消息監(jiān)聽者釋放這些,下面看下使用的場(chǎng)景圖。
如上圖,經(jīng)常會(huì)遇到這種情況,當(dāng)觸發(fā)某個(gè)操作或者監(jiān)聽到某種狀態(tài)變化后,每個(gè)View都要做出相應(yīng)的變化,這種情況我們就需要寫分類或者通知等等方式去處理這種操作,而且如果界面出現(xiàn)遺漏很容易造成奔潰啥的,那么是否有簡(jiǎn)便安全的方式呢?有的,下面隆重介紹我的代理模式,實(shí)現(xiàn)一對(duì)多功能。那么按照常規(guī)操作,我們應(yīng)該先進(jìn)行普及一些知識(shí),這樣更容易看懂代碼。
NSMapTable
蘋果官方是這么解釋的:
A collection similar to a dictionary, but with a broader range of available memory semantics.
KG翻譯版本是這么解釋的:
類似于字典的集合,但具有更廣泛的可用內(nèi)存語(yǔ)義。
通俗點(diǎn)解釋就是:和NSDictionary類似,但是也有區(qū)別,對(duì)于內(nèi)存這塊做了相應(yīng)的優(yōu)化。主要區(qū)別在于以下幾點(diǎn):
- key-value鍵值可以設(shè)置一個(gè)弱引用、一個(gè)強(qiáng)引用
- key-value鍵值可以都設(shè)置為弱引用
- key-value鍵值可以都設(shè)置為強(qiáng)引用
- 無(wú)論是key還是value都可以包含任意指針,內(nèi)存不限于對(duì)象
NSPointerArray
蘋果官方是這么解釋的:
A collection similar to an array, but with a broader range of available memory semantics.
KG翻譯版本是這么解釋的:
類似于數(shù)組的集合,但具有更廣泛的可用內(nèi)存語(yǔ)義。
通俗帶你解釋就是:和NSArray類似,但是也有區(qū)別,對(duì)于內(nèi)存處理做了優(yōu)化。區(qū)別于NSArray的點(diǎn)主要有:
- 可以保存
nil值 - 可以進(jìn)行插入或者刪除
nil或者刪除指定索引處的指針 - 可以初始化數(shù)組,對(duì)數(shù)組內(nèi)的元素使用強(qiáng)引用維護(hù)
- 可以初始化數(shù)組,對(duì)數(shù)組內(nèi)的元素使用弱引用維護(hù)
NSHashTable
蘋果官方是這么解釋的:
A collection similar to a set, but with broader range of available memory semantics.
KG翻譯版本是這么解釋的:
類似于集合的集合,但具有更廣泛的可用內(nèi)存語(yǔ)義。
通俗點(diǎn)解釋就是:和NSSet類似,但是也有區(qū)別,對(duì)于內(nèi)存這塊做了相應(yīng)的優(yōu)化。主要區(qū)別在于以下幾點(diǎn):
- 它可以持有對(duì)其成員的弱引用
- 它的成員可以在輸入時(shí)復(fù)制,也可以使用指針標(biāo)識(shí)進(jìn)行相等和散列
- 它可以包含任意指針(其成員不限于對(duì)象)
- 可以初始化集合,對(duì)集合內(nèi)的內(nèi)容使用弱引用
自定義代理管理類
1、在iOS開發(fā)中多個(gè)對(duì)象之間進(jìn)行消息交互,我們常用的方式有以下幾種:
- 通知:一對(duì)多,只負(fù)責(zé)消息發(fā)送,不負(fù)責(zé)消息狀態(tài)回調(diào)
- 代理:一對(duì)一,判斷消息能否正常響應(yīng)
- Block:一對(duì)一,判斷回調(diào)是否實(shí)現(xiàn)
- KVO:一對(duì)多,消息訂閱后就可以收到監(jiān)聽回調(diào)
雖然我們有多種方式實(shí)現(xiàn)一對(duì)多的通信,但是以上幾種都是存在相對(duì)的缺點(diǎn),通知來(lái)說耦合性很高,而且性能消耗很大;KVO的話細(xì)節(jié)比較多,特別是注冊(cè)監(jiān)聽后的移除,如果忘記那就是毀滅性的打擊。所以我想到能否實(shí)現(xiàn)代理的一對(duì)多呢?經(jīng)過一頓猛如虎的操作,我發(fā)現(xiàn)是可以的,而且使用起來(lái)是非常舒服,下面就開始進(jìn)入主題。
2、設(shè)計(jì)思路的話也比較簡(jiǎn)單,就是使用一個(gè)中間類,去遵守各種協(xié)議,然后當(dāng)有對(duì)象需要遵守協(xié)議的時(shí)候,只需要將對(duì)象注冊(cè)到中間類中,只要委托方調(diào)用了協(xié)議方法,那么代理方法實(shí)現(xiàn)的地方就會(huì)走相應(yīng)的方法。下面看下協(xié)議管理類的主要代碼:
3、以上是代理類的實(shí)現(xiàn),那么再看下使用:
沒錯(cuò)就是這么簡(jiǎn)單,只需要在需要遵守協(xié)議的類中實(shí)現(xiàn)協(xié)議的方法,然后注冊(cè)協(xié)議以及遵守者到代理管理類中,當(dāng)委托方調(diào)用協(xié)議方法時(shí),所有注冊(cè)了協(xié)議的類都會(huì)收到協(xié)議方法回調(diào),而且如果不需要遵守的時(shí)候也很簡(jiǎn)單,只需要調(diào)用[[KGDelegate shareInstance] removeTarget:self withProtocol:NSProtocolFromString(@"KGPersonDelegate")];就能取消代理注冊(cè)了,而且就算類注冊(cè)的類已經(jīng)釋放了,也不會(huì)造成內(nèi)存泄露。