iOS 為對象添加一個釋放時觸發(fā)的Block

有時我們需要在一個對象生命周期結束的時候觸發(fā)一個操作,希望當該對象dealloc的時候調(diào)用一個外部指定的block,但又不希望直接hook dealloc方法,這樣侵入性太強了.怎么辦呢训堆?
打個廣告:問題驗證demo里有相關的驗證蜻韭,可以去看看

為什么不直接寫個block的屬性,在dealloc的時候調(diào)用呢缔逛?

下面介紹一個簡單的實現(xiàn)方法:

通過一個category給外部暴露一個block注入的接口画侣,內(nèi)部將該block封裝到一個寄生對象的dealloc中(Parasite),該寄生對象是以關聯(lián)對象的形式與對象綁定冰悠。在對象dealloc的時候,觸發(fā)對象關聯(lián)對象的釋放配乱,從而釋放寄生對象溉卓,寄生對象觸發(fā)其dealloc同時觸發(fā)block調(diào)用

  • 原理:所有的寄生對象通過runtime的AssociatedObject機制與宿主共存亡,從而達到監(jiān)控宿主生命周期的目的.

下面就是代碼的實現(xiàn):

  • NSObject+Guard.h
#import <Foundation/Foundation.h>

@interface NSObject (Guard)

/**
 @brief 添加一個block,當該對象釋放時被調(diào)用
 **/
- (void)guard_addDeallocBlock:(void(^)(void))block;

@end

  • NSObject+Guard.m
#import "NSObject+Guard.h"
#import <objc/runtime.h>

/// 此為一 寄生類
@interface Parasite : NSObject
@property (nonatomic, copy) void(^deallocBlock)(void);
@end

@implementation Parasite

- (void)dealloc {
    if (self.deallocBlock) {
        self.deallocBlock();
    }
}

@end

@implementation NSObject (Guard)

- (void)guard_addDeallocBlock:(void(^)(void))block {
    ///self是用來區(qū)分NSObject的子類的皮迟。
    
    ///此處有個同步操作,防止多線程數(shù)據(jù)競爭的干擾
    @synchronized (self) {
        static NSString *kAssociatedKey = @"kAssociatedKey";
        /// 數(shù)組桑寨,用于存放多個寄生對象
        NSMutableArray *parasiteList = objc_getAssociatedObject(self, &kAssociatedKey);
        if (!parasiteList) {
            parasiteList = [NSMutableArray new];
            objc_setAssociatedObject(self, &kAssociatedKey, parasiteList, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
        /// 創(chuàng)建寄生類 存放block
        Parasite *parasite = [Parasite new];
        parasite.deallocBlock = block;
        [parasiteList addObject: parasite];
    }
}

@end

細節(jié)點:

  1. 寄生對象有一屬性block伏尼,其實用于接收外部注入的block,好在寄生對象dealloc時尉尾,獲取并調(diào)用

  2. 分類的實現(xiàn)中爆阶,關聯(lián)對象為一可變數(shù)組,是為了讓對象可以被注入多個釋放回調(diào)(同時創(chuàng)建了用于存放釋放回調(diào)的寄生對象)沙咏。統(tǒng)一由數(shù)組保存即可

思考

為什么要大費周章的加入runtime來注入block辨图?對象直接創(chuàng)建一個block屬性,在dealloc的時候調(diào)用芭碍,不也一樣可以執(zhí)行徒役?

個人有兩個不成熟的想法:

  1. 簡單點:此方法可以為對象注入多個不同block,不再需要重新定義窖壕,麻煩

  2. 鴻觀點:此方法是一個不侵入類的做法。不需要關聯(lián)到具體類(即不需要在每個類的dealloc中都操作一遍杉女,此為侵入)瞻讽,比較通用。

以上為個人淺見熏挎,歡迎各位大神參加討論

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末速勇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坎拐,更是在濱河造成了極大的恐慌烦磁,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哼勇,死亡現(xiàn)場離奇詭異都伪,居然都是意外死亡,警方通過查閱死者的電腦和手機积担,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門陨晶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人帝璧,你說我怎么就攤上這事先誉。” “怎么了的烁?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵褐耳,是天一觀的道長。 經(jīng)常有香客問我渴庆,道長铃芦,這世上最難降的妖魔是什么买雾? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮杨帽,結果婚禮上漓穿,老公的妹妹穿的比我還像新娘。我一直安慰自己注盈,他們只是感情好晃危,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著老客,像睡著了一般僚饭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胧砰,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天鳍鸵,我揣著相機與錄音,去河邊找鬼尉间。 笑死偿乖,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的哲嘲。 我是一名探鬼主播贪薪,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼眠副!你這毒婦竟也來了画切?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤囱怕,失蹤者是張志新(化名)和其女友劉穎霍弹,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娃弓,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡典格,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了忘闻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钝计。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖齐佳,靈堂內(nèi)的尸體忽然破棺而出私恬,到底是詐尸還是另有隱情,我是刑警寧澤炼吴,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布本鸣,位于F島的核電站,受9級特大地震影響硅蹦,放射性物質(zhì)發(fā)生泄漏荣德。R本人自食惡果不足惜闷煤,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涮瞻。 院中可真熱鬧鲤拿,春花似錦、人聲如沸署咽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宁否。三九已至窒升,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慕匠,已是汗流浹背饱须。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留台谊,地道東北人蓉媳。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像青伤,于是被迫代替她去往敵國和親督怜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

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