iOS runtime之-方法交換

使用場(chǎng)景

在我們使用系統(tǒng)的方法時(shí)枢步,功能有可能不夠用,或者在想在調(diào)用系統(tǒng)的方法時(shí)娱挨,加一些判斷余指。當(dāng)然我可以繼承系統(tǒng)的類,然后重寫該方法跷坝。但是有可能項(xiàng)目做得時(shí)間比較長(zhǎng)酵镜,一開始并沒有繼承。這時(shí)候再去繼承就會(huì)花費(fèi)一些時(shí)間柴钻。而且公司來(lái)了新人的淮韭,并不熟悉公司代碼框架的時(shí)候,有可能會(huì)忘記繼承顿颅。所以這時(shí)候我們就可以用運(yùn)行時(shí)給系統(tǒng)方法動(dòng)態(tài)添加一些代碼缸濒。

使用步驟

  • 創(chuàng)建你想交換方法所在類的分類。比如你想在調(diào)用 viewWillAppear時(shí)添加一些代碼粱腻,那么你就新建一個(gè)UIViewController的分類庇配。
  • 包含頭文件#import <objc/runtime.h>
  • 實(shí)現(xiàn)+ (void)load{}方法,在這個(gè)方法里面動(dòng)態(tài)交換兩個(gè)方法的地址绍些,實(shí)現(xiàn)功能捞慌。這個(gè)方法會(huì)在程序加載分類到內(nèi)存的時(shí)候就調(diào)用。

主要用到的運(yùn)行時(shí)方法

  • Method class_getClassMethod(Class cls, SEL name) cls:需要交換的類方法的所屬類 class SEL:該類方法 獲取一個(gè)類的類方法的地址
  • Method class_getInstanceMethod(Class cls, SEL name) cls:需要交換的類實(shí)例方法的所屬類 class SEL:該類的實(shí)例方法 獲取一個(gè)類的實(shí)例方法地址
  • BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) cls:被添加方法的類名 name:方法名 imp:實(shí)現(xiàn)這個(gè)方法的函數(shù) types:一個(gè)定義該函數(shù)返回值類型和參數(shù)類型的字符串 動(dòng)態(tài)的給一個(gè)類添加一個(gè)方法
  • IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types) 參數(shù)如class_addMethod類似 該函數(shù)可以在運(yùn)行時(shí)動(dòng)態(tài)替換某個(gè)類的函數(shù)實(shí)現(xiàn)
  • void method_exchangeImplementations(Method m1, Method m2) 交換兩個(gè)方法的地址

例子

在我們開發(fā)中使用可變數(shù)組NSMutableArray 取數(shù)組里面的元素一旦越界就會(huì)崩潰柬批。那么有什么辦法啸澡,讓線上用戶發(fā)生數(shù)組越界的時(shí)候不崩潰呢。這時(shí)候就可以用運(yùn)行時(shí)來(lái)實(shí)現(xiàn)這個(gè)功能氮帐。

新建NSMutableArray的分類嗅虏,包含runtime頭文件

// load方法會(huì)在類第一次加載到內(nèi)存的時(shí)候被調(diào)用  
+ (void)load {
    //方法交換只用執(zhí)行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class cls = NSClassFromString(@"__NSArrayM");
        // 獲取系統(tǒng)數(shù)組的selector
        SEL   systemSelector = @selector(objectAtIndex:);
        // 自己要交換的selector
        SEL   swizzledSelector = @selector(zwb_safeObjectAtIndex:);
        // 兩個(gè)方法的Method
        Method originalMethod = class_getInstanceMethod(cls, systemSelector);
        Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
        //  動(dòng)態(tài)添加方法
        if (class_addMethod(cls, systemSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) {
            // 添加成功的話將被交換方法的實(shí)現(xiàn)替換到這個(gè)并不存在的實(shí)現(xiàn)
            class_replaceMethod(cls, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        }else {
            //添加不成功,交換兩個(gè)方法的實(shí)現(xiàn)
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}
 - (id)zwb_safeObjectAtIndex:(NSUInteger)index {
    if (self.count > index) {
        //一定是自己調(diào)用自己上沐,不會(huì)死循環(huán)皮服,因?yàn)榈刂芬呀?jīng)交換,其實(shí)調(diào)用的是系統(tǒng)的objectAtIndex
        return [self zwb_safeObjectAtIndex:index];
    }else {
        NSLog(@"數(shù)組越界");
        return nil;
    }
}

當(dāng)然數(shù)組的其他方法也可以用這種方式防止崩潰参咙,大家可以試試龄广。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蕴侧,隨后出現(xiàn)的幾起案子择同,更是在濱河造成了極大的恐慌,老刑警劉巖净宵,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敲才,死亡現(xiàn)場(chǎng)離奇詭異裹纳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)归斤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門痊夭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人脏里,你說(shuō)我怎么就攤上這事她我。” “怎么了迫横?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵番舆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我矾踱,道長(zhǎng)恨狈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任呛讲,我火速辦了婚禮禾怠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贝搁。我一直安慰自己吗氏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布雷逆。 她就那樣靜靜地躺著弦讽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪膀哲。 梳的紋絲不亂的頭發(fā)上往产,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音某宪,去河邊找鬼仿村。 笑死,一個(gè)胖子當(dāng)著我的面吹牛兴喂,可吹牛的內(nèi)容都是我干的奠宜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼瞻想,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了娩嚼?” 一聲冷哼從身側(cè)響起蘑险,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎岳悟,沒想到半個(gè)月后佃迄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泼差,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年呵俏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堆缘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡普碎,死狀恐怖吼肥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情麻车,我是刑警寧澤缀皱,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站动猬,受9級(jí)特大地震影響啤斗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赁咙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一钮莲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧彼水,春花似錦崔拥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至叛赚,卻和暖如春澡绩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俺附。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工肥卡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人事镣。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓步鉴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親璃哟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子氛琢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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