Protocol協(xié)議分發(fā)器

Protocol協(xié)議代理在開發(fā)中應(yīng)用頻繁阶牍,開發(fā)者經(jīng)常會遇到一個問題——事件的連續(xù)傳遞喷面。比如,為了隔離封裝走孽,開發(fā)者可能經(jīng)常會把tableview的delegate或者datesource抽離出獨(dú)立的對象惧辈,而其它對象(比如VC)需要獲取某些delegate事件時,只能通過事件的二次傳遞磕瓷。有沒有更簡單的方法了盒齿?協(xié)議分發(fā)器正好可以派上用場

話不多說,先上干貨:HJProtocolDispatcher是一個協(xié)議實(shí)現(xiàn)分發(fā)器困食,通過該工具能夠輕易實(shí)現(xiàn)將協(xié)議事件分發(fā)給多個實(shí)現(xiàn)者边翁。比如最常見的tableview的delegate協(xié)議,通過HJProtocolDispatcher硕盹,能夠非常容易的分發(fā)給多個對象符匾,具體可參考Demo

self.tableView.delegate = AOProtocolDispatcher(UITableViewDelegate, self, self.delegateSource);

原理解析

原理并不復(fù)雜, 協(xié)議分發(fā)器Dispatcher并不實(shí)現(xiàn)Protocol協(xié)議莱睁,其只需將對應(yīng)的Protocol事件分發(fā)給不同的實(shí)現(xiàn)者Implemertor待讳。如何實(shí)現(xiàn)分發(fā)?

熟悉類Class響應(yīng)鏈的童鞋都知道仰剿,NSObject對象主要通過以下函數(shù)響應(yīng)未實(shí)現(xiàn)的Selector函數(shù)調(diào)用

- (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);

- (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE("");

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector

因此创淡,協(xié)議分發(fā)器Dispatcher可以在該函數(shù)中將Protocol中Selector的調(diào)用傳遞給實(shí)現(xiàn)者Implemertor,由實(shí)現(xiàn)者Implemertor實(shí)現(xiàn)具體的Selector函數(shù)即可

- (void)forwardInvocation:(NSInvocation *)anInvocation {

    SEL aSelector = anInvocation.selector;

    if (!ProtocolContainSel(self.prococol, aSelector)) {

        [super forwardInvocation:anInvocation];

        return;

    }

    for (ImplemertorContext *implemertorContext in self.implemertors) {

        if ([implemertorContext.implemertor respondsToSelector:aSelector]) {

            [anInvocation invokeWithTarget:implemertorContext.implemertor];

        }

    }

}

設(shè)計關(guān)鍵

如何做到只對Protocol中Selector函數(shù)的調(diào)用做分發(fā)是設(shè)計的關(guān)鍵南吮,系統(tǒng)提供有函數(shù)

objc_method_description protocol_getMethodDescription(Protocol *p, SEL aSel, BOOL isRequiredMethod, BOOL isInstanceMethod)

通過以下方法即可判斷Selector是否屬于某一Protocol

struct objc_method_description MethodDescriptionForSELInProtocol(Protocol *protocol, SEL sel) {

    struct objc_method_description description = protocol_getMethodDescription(protocol, sel, YES, YES);

    if (description.types) {

        return description;

    }

    description = protocol_getMethodDescription(protocol, sel, NO, YES);

    if (description.types) {

        return description;

    }

    return (struct objc_method_description){NULL, NULL};

}

BOOL ProtocolContainSel(Protocol *protocol, SEL sel) {

    return MethodDescriptionForSELInProtocol(protocol, sel).types ? YES: NO;

}

注意事項

協(xié)議分發(fā)器使用需要了解如何處理帶有返回值的函數(shù) 琳彩,比如

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

我們知道,iOS中,函數(shù)執(zhí)行返回的結(jié)果存在于寄存器R0中露乏,后執(zhí)行的會覆蓋先執(zhí)行的結(jié)果碧浊。因此,當(dāng)遇到有返回結(jié)果的函數(shù)時瘟仿,返回結(jié)果以后執(zhí)行的函數(shù)返回結(jié)果為最終值箱锐,以Demo為例

self.tableView.delegate = AOProtocolDispatcher(UITableViewDelegate, self, self.delegateSource);

TableView的DataSource以后面的self.delegateSource中實(shí)現(xiàn)函數(shù)返回的結(jié)果為準(zhǔn)

備注

開發(fā)完本項目后發(fā)現(xiàn)網(wǎng)上已有朋友實(shí)現(xiàn)了協(xié)議分發(fā)器AOMultiproxier,因此劳较,技術(shù)版權(quán)屬于原作者驹止,本文只做宣傳,特此說明观蜗!

注:二次傳遞臊恋,在demo里面就是viewController中會響應(yīng)這個代理方法,在delegateSource中也會響應(yīng)這個代理方法墓捻。也就是兩個地方都實(shí)現(xiàn)代理方法抖仅,會依次響應(yīng)。

轉(zhuǎn)載:http://www.olinone.com/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末砖第,一起剝皮案震驚了整個濱河市撤卢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌梧兼,老刑警劉巖凸丸,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異袱院,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瞭稼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門忽洛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人环肘,你說我怎么就攤上這事欲虚。” “怎么了悔雹?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵复哆,是天一觀的道長。 經(jīng)常有香客問我腌零,道長梯找,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任益涧,我火速辦了婚禮锈锤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己久免,他們只是感情好浅辙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著阎姥,像睡著了一般记舆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呼巴,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天泽腮,我揣著相機(jī)與錄音,去河邊找鬼伊磺。 笑死盛正,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的屑埋。 我是一名探鬼主播豪筝,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼摘能!你這毒婦竟也來了续崖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤团搞,失蹤者是張志新(化名)和其女友劉穎严望,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逻恐,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡像吻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了复隆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拨匆。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖挽拂,靈堂內(nèi)的尸體忽然破棺而出惭每,到底是詐尸還是另有隱情,我是刑警寧澤亏栈,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布台腥,位于F島的核電站,受9級特大地震影響绒北,放射性物質(zhì)發(fā)生泄漏黎侈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一闷游、第九天 我趴在偏房一處隱蔽的房頂上張望蜓竹。 院中可真熱鬧箕母,春花似錦、人聲如沸俱济。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蛛碌。三九已至聂喇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蔚携,已是汗流浹背希太。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留酝蜒,地道東北人誊辉。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像亡脑,于是被迫代替她去往敵國和親堕澄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354