iOS Block一對(duì)多回調(diào)的實(shí)現(xiàn)

前言

我們都知道,回調(diào)的方案有Block杯瞻、代理镐牺、通知。要想實(shí)現(xiàn)一對(duì)多就要用通知又兵。而且很方便的在多個(gè)地方進(jìn)行回調(diào)任柜,實(shí)現(xiàn)我們?nèi)我獾姆椒ā?br> 然而是否考慮過(guò)用Block去實(shí)現(xiàn)一對(duì)多的回調(diào)卒废。注意:不是無(wú)聊的想象哦沛厨,可以讓我們看到另一面。

原理

一般情況下摔认,Block的回調(diào)確實(shí)是一對(duì)一的逆皮。要想實(shí)現(xiàn)一對(duì)多,我們能想到什么参袱?緩存block电谣,循環(huán)調(diào)用秽梅。沒(méi)錯(cuò),本質(zhì)上是這樣〗宋現(xiàn)在我們需要考慮一下幾個(gè)問(wèn)題:

1企垦、用什么緩存來(lái)保證不會(huì)循環(huán)引用?
2晒来、Block的一對(duì)一钞诡?
3、如何遍歷調(diào)用湃崩?
4荧降、還有不想用的Block如何快捷移除?

下面我們來(lái)一一解決以上問(wèn)題攒读。

實(shí)現(xiàn)方案

1朵诫、第一個(gè)問(wèn)題:
首先我們可以考慮使用 NSMapTable 來(lái)緩存Block。因?yàn)檫@種緩存方式可以設(shè)置KEY和Value的緩存策略薄扁,并且可以把KEY設(shè)置成Object剪返。設(shè)置Value的緩存策略,可以讓我們把綁定的Block的Target也就是我們Value設(shè)置成 NSPointerFunctionsWeakMemory 這樣就可以在Target釋放的時(shí)候邓梅,自動(dòng)移除我們的此條數(shù)據(jù)随夸。

2、第二個(gè)問(wèn)題
我們可以使用 runtime 的關(guān)聯(lián)對(duì)象震放,關(guān)聯(lián)當(dāng)前監(jiān)聽(tīng)對(duì)象 observer 和Block宾毒。

3、第三個(gè)問(wèn)題
遍歷的時(shí)候殿遂,遍歷所有的存儲(chǔ)的 observer诈铛,找出其相對(duì)應(yīng)的KEY,再用KEY找到所關(guān)聯(lián)的Block墨礁。從而實(shí)現(xiàn)回調(diào)幢竹。

4、第四個(gè)問(wèn)題
其實(shí)第四個(gè)問(wèn)題恩静,在第一個(gè)問(wèn)題的基礎(chǔ)上也已經(jīng)得到了解決焕毫。但是我們有可能在一個(gè)類里,也就是同一個(gè)Observer中有多個(gè)回調(diào)驶乾,此時(shí)我們需要的KeyTable中的數(shù)據(jù)無(wú)法移除邑飒。此時(shí)單獨(dú)Remove即可

具體實(shí)現(xiàn)如下:

@interface Manger ()

@property (nonatomic, strong) NSMapTable *valueTable;

@property (nonatomic, strong) NSMapTable *keyTable;

@end
@implementation Manger

+ (instancetype)sharedInstance
{
    static Manger *gInteractor = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!gInteractor) {
            gInteractor = [Manger new];
            gInteractor.valueTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableWeakMemory];
            gInteractor.keyTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableWeakMemory];
        }
    });
    return gInteractor;
}

- (void)clickSelector:(id)obsever callBack:(void(^)(NSString *callStr))callBack {
    
    // 使用內(nèi)存地址保證一個(gè)對(duì)象置監(jiān)聽(tīng)一次
    NSString *key = [NSString stringWithFormat:@"%@-key", [NSString stringWithFormat:@"%p", obsever]];
    NSString *keyValue = [key stringByAppendingString:@"-KeyBlock"];
    
    [self.valueTable setObject:obsever forKey:key];
    [self.keyTable setObject:keyValue forKey:key];
    
    // keyValue 和 block 進(jìn)行關(guān)聯(lián)
    objc_setAssociatedObject(obsever, CFBridgingRetain(keyValue), callBack, OBJC_ASSOCIATION_COPY);
}

- (void)clickSelector {
    
    NSArray <NSString *>*keyArr = [[self.valueTable keyEnumerator] allObjects];
    
    [keyArr enumerateObjectsUsingBlock:^(NSString * _Nonnull key, NSUInteger idx, BOOL * _Nonnull stop) {
        
        id observe = [self.valueTable objectForKey:key];
        NSString *valueKey = [self.keyTable objectForKey:key];
        void(^block)(NSString *callStr) = objc_getAssociatedObject(observe, (__bridge const void * _Nonnull)(valueKey));
        
        if (block) {
            block([NSString stringWithFormat:@"%@", NSStringFromClass([self class])]);
        }
    }];
    
    NSLog(@"%@\n%@", self.valueTable, self.keyTable);
}

/// 移除的時(shí)候,僅僅只是移除的KeyTable數(shù)據(jù)级乐,因?yàn)閂alueTable中的數(shù)據(jù)疙咸,隨著Observer的釋放而自動(dòng)移除了
- (void)remove:(id)obj {
    
    NSString *key = [NSString stringWithFormat:@"%@-key", [NSString stringWithFormat:@"%p", obj]];
    [self.keyTable removeObjectForKey:key];
}

@end
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市风科,隨后出現(xiàn)的幾起案子撒轮,更是在濱河造成了極大的恐慌乞旦,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件题山,死亡現(xiàn)場(chǎng)離奇詭異兰粉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)顶瞳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門亲桦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人浊仆,你說(shuō)我怎么就攤上這事客峭。” “怎么了抡柿?”我有些...
    開(kāi)封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵舔琅,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我洲劣,道長(zhǎng)备蚓,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任囱稽,我火速辦了婚禮郊尝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘战惊。我一直安慰自己流昏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布吞获。 她就那樣靜靜地躺著况凉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪各拷。 梳的紋絲不亂的頭發(fā)上刁绒,一...
    開(kāi)封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音烤黍,去河邊找鬼知市。 笑死,一個(gè)胖子當(dāng)著我的面吹牛速蕊,可吹牛的內(nèi)容都是我干的嫂丙。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼互例,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奢入!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起媳叨,我...
    開(kāi)封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤腥光,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后糊秆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體武福,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年痘番,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捉片。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡汞舱,死狀恐怖伍纫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昂芜,我是刑警寧澤莹规,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站泌神,受9級(jí)特大地震影響良漱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜欢际,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一母市、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧损趋,春花似錦患久、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至括荡,卻和暖如春高镐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背畸冲。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工嫉髓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邑闲。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓算行,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親苫耸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子州邢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,089評(píng)論 1 32
  • iOS網(wǎng)絡(luò)架構(gòu)討論梳理整理中。褪子。量淌。 其實(shí)如果沒(méi)有APIManager這一層是沒(méi)法使用delegate的骗村,畢竟多個(gè)單...
    yhtang閱讀 5,165評(píng)論 1 23
  • 面向?qū)ο蟮娜筇匦裕悍庋b、繼承呀枢、多態(tài) OC內(nèi)存管理 _strong 引用計(jì)數(shù)器來(lái)控制對(duì)象的生命周期胚股。 _weak...
    運(yùn)氣不夠技術(shù)湊閱讀 1,085評(píng)論 0 10
  • 吶,我們還在一起說(shuō)明還有在一起的價(jià)值裙秋,對(duì)吧琅拌。 我會(huì)以我理解的方式表達(dá)善意和關(guān)心,歡迎指正摘刑。 但也會(huì)努力試著以自己的...
    榴蓮子的流連地閱讀 116評(píng)論 0 0