分享OC runtime進(jìn)行時(shí)入門級(jí)別的運(yùn)用

智勇博客:
最近比較有空非洲,在這里分享一下OC的底層runtime進(jìn)行時(shí)的一些簡單運(yùn)用,比較適合初學(xué)者來學(xué)習(xí)了解一下。
先說幾句干貨,讓大家了解一些 什么叫做runtime進(jìn)行時(shí)钾怔。
OC語言分4個(gè)階段:
1.編寫程序階段凝垛,也就是大家每天都在做的桃焕。
2.編譯階段
3.鏈接階段
4.運(yùn)行階段而账,也就是runtime進(jìn)行時(shí)

OC雖然在編譯時(shí),會(huì)進(jìn)行一次代碼檢測。但這緊緊只是檢查一些簡單的操作牍颈,比如有沒有寫錯(cuò)什么關(guān)鍵字 哪里的語法有沒有寫錯(cuò),打個(gè)比喻就是像個(gè)老師檢查學(xué)生的作文中有沒有錯(cuò)別字和病句一樣徒爹。如果有錯(cuò)誤就會(huì)有errors或者warning信息提示出來,那都是編譯器檢查出來的泡躯。

進(jìn)行時(shí)就是代碼跑起來惰拱,被裝載到內(nèi)存中去了披泪。而進(jìn)行時(shí)類型檢查就與前面講的編譯時(shí)類型檢查不一樣。不是簡單的掃描代碼。而是在內(nèi)存中做些操作雏吭,做些判斷婚温。如果出現(xiàn)問題則直接崩潰掺逼。

這篇文章主要的是介紹runtime的入門級(jí)運(yùn)用,下面來下實(shí)際點(diǎn)的。

runtime的使用場景其實(shí)可以有很多辕漂,只不過大家平常寫代碼時(shí)并沒有往這方面去想,自然就運(yùn)用不上runtime了
比如需求是:
我們執(zhí)行兩段不一樣的代碼跋涣,但是執(zhí)行的方法名字需要一樣遣臼。某個(gè)時(shí)候調(diào)用這個(gè)方法 是執(zhí)行代碼段1 某個(gè)時(shí)候調(diào)用這個(gè)方法 就是執(zhí)行代碼段2之碗。
還有一個(gè)就是:
在一個(gè)完整的項(xiàng)目中,突然項(xiàng)目經(jīng)理需要修改一個(gè)HUD彈框顯示的背景顏色和文字祭往。而這個(gè)HUD又在整個(gè)項(xiàng)目中的無數(shù)個(gè)地方使用過。那么此時(shí)有一個(gè)很苦力很low的方法栏妖,就是整個(gè)項(xiàng)目中逐一修改乱豆。
還有很多案例等,我就不一一舉例了吊趾。
這些時(shí)候 其實(shí)都是可以用runtime來解決宛裕,就是幾句代碼的事而已。

下面介紹2個(gè)runtime中的方法:
method_exchangeImplementations 來交換2個(gè)方法中的IMP论泛,
method_setImplementation 來直接設(shè)置某個(gè)方法的IMP

IMP可能某些同學(xué)會(huì)比較陌生一點(diǎn)揩尸,起始IMP可以看做為一個(gè)指針存儲(chǔ)器,OC中屁奏,調(diào)用某個(gè)函數(shù)岩榆,轉(zhuǎn)換為C語言就是調(diào)用這個(gè)IMP指向的函數(shù) 說白一點(diǎn),就是通過IMP來找到需要調(diào)用的函數(shù)!

理解了IMP 那么需要偷龍轉(zhuǎn)鳳 就簡單多了勇边。只要把函數(shù)的IMP偷偷轉(zhuǎn)換掉犹撒,到時(shí)候系統(tǒng)調(diào)用的該函數(shù)的時(shí)候,其實(shí)就是調(diào)用了我們新傳進(jìn)去的IMP指向的函數(shù)了粒褒。

這里主要介紹一下method_exchangeImplementations 這個(gè)運(yùn)行時(shí)方法识颊,其他方法之后會(huì)陸續(xù)再寫另一篇文章來跟大家繼續(xù)講解。

下面直接上一段代碼:

+(void)load {
    //創(chuàng)建一個(gè)類型   也可以直接寫成  [NSArray class]
    Class targetClass = [NSClassFromString(@"NSArray") class];
    //返回一個(gè)指定的函數(shù) 這個(gè)函數(shù)指向 [self override_lastObject] 這個(gè)函數(shù)
    Method m1 = class_getInstanceMethod([self class], @selector(override_firstObject));

    /**
     *  給一個(gè)指定的類新增一個(gè)函數(shù)方法
     *
     *   targetClass         需要新增函數(shù)的類
     *   override_lastObject 新增函數(shù)的名字
     *   imp                 新增函數(shù)調(diào)用時(shí) 指向的地址
     *   char *types         字符串描述這個(gè)函數(shù)的參數(shù)和返回類型
     *
     *
     *   返回BOOL值
     */
    BOOL isbool = class_addMethod(targetClass, @selector(override_firstObject), method_getImplementation(m1), method_getTypeEncoding(m1));
    if (isbool == YES) {
        NSLog(@"添加方法成功");
    } else {
        NSLog(@"添加方法失敗");
    }

    //提取這個(gè)類targetClass  的這個(gè)override_firstObject函數(shù)方法
    Method m2 = class_getInstanceMethod(targetClass, @selector(override_firstObject));
    //提取這個(gè)類targetClass  的這個(gè)firstObject函數(shù)方法
    Method m3 = class_getInstanceMethod(targetClass, @selector(firstObject));

    //將兩個(gè)函數(shù)的Imp指向?qū)ο?對(duì)換
    method_exchangeImplementations(m2, m3);
}

上面的代碼中 直接在+load方法中實(shí)現(xiàn) 整個(gè)程序運(yùn)行的時(shí)候把代碼噻進(jìn)內(nèi)存中的時(shí)候就會(huì)調(diào)用一次奕坟。也就是程序剛開始運(yùn)行的時(shí)候 我們就已經(jīng)把需要調(diào)換的方法 成功的調(diào)換了
之后只要有NSArray調(diào)用firstObject這個(gè)方法的時(shí)候
就會(huì)調(diào)用了我們自己新寫的方法override_firstObject祥款。
相反也是,只要調(diào)用NSArray的override_firstObject方法時(shí)
就會(huì)調(diào)用原來的firstObject方法了月杉。

需要注意的是 因?yàn)槲覀冊摰氖钦麄€(gè)NSArray類镰踏,所以會(huì)影響到整個(gè)程序的,并不是只影響這個(gè)控制器 或者 這個(gè)頁面的哦沙合!所以使用的時(shí)候需要注意奠伪,別亂該系統(tǒng)級(jí)別的控件!

一下代碼是測試上面的方法 是否成功的:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *array = @[@"1", @"2"];
    NSString *str = [array firstObject];
    NSLog(@"str = %@",str);
}

-(void)override_firstObject {
    NSLog(@"調(diào)用自己新寫的firstObject方法");
    [self override_firstObject];
}

上面看起來override_firstObject方法中 好像是一個(gè)遞歸死循環(huán)了首懈,但其實(shí)不是绊率,上面也說過了,override_firstObject 和 firstObject 兩個(gè)方法是做了Imp調(diào)換的究履。所以不會(huì)造成遞歸滤否。

這里的控制臺(tái)輸出順序是:
2017-02-16 16:46:54.917 textDemo[4183:192569] 添加方法成功
2017-02-16 16:46:54.997 textDemo[4183:192569] 調(diào)用自己新寫的lastObject方法
2017-02-16 16:46:54.998 texDemo[4183:192569] str = 1

控制臺(tái)這樣的輸出 已經(jīng)證明了我們將兩個(gè)方法的Imp對(duì)換是成功的。
上面只是為了簡化代碼 所以隨便寫來證實(shí)method_exchangeImplementations方法的運(yùn)用最仑。
只要掌握了runtime的運(yùn)用藐俺,在以后的敲代碼過程中 會(huì)有一個(gè)很大的幫助,能幫助大家走少很多彎路的喔泥彤!

感謝大家能看到完整篇文章欲芹! 在下一篇文章中,我將繼續(xù)分享一個(gè)我封裝的第三方吟吝。這個(gè)第三方里菱父,主要功能都是依賴runtime的。
預(yù)告:下一篇文章將會(huì)在實(shí)戰(zhàn)項(xiàng)目中 運(yùn)用到一下幾個(gè)runtime的方法剑逃,并且會(huì)有詳細(xì)的講解以下方法的作用 歡迎初學(xué)者來留意一下:
class_getInstanceMethod
class_addMethod
method_getImplementation
method_getTypeEncoding
method_exchangeImplementations
objc_setAssociatedObject
objc_getAssociatedObject

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末浙宜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蛹磺,更是在濱河造成了極大的恐慌粟瞬,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萤捆,死亡現(xiàn)場離奇詭異裙品,居然都是意外死亡乓梨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門清酥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蕴侣,你說我怎么就攤上這事焰轻。” “怎么了昆雀?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵辱志,是天一觀的道長。 經(jīng)常有香客問我狞膘,道長揩懒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任挽封,我火速辦了婚禮已球,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘辅愿。我一直安慰自己智亮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布点待。 她就那樣靜靜地躺著阔蛉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪癞埠。 梳的紋絲不亂的頭發(fā)上状原,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音苗踪,去河邊找鬼颠区。 笑死,一個(gè)胖子當(dāng)著我的面吹牛通铲,可吹牛的內(nèi)容都是我干的瓦呼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼测暗,長吁一口氣:“原來是場噩夢啊……” “哼央串!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碗啄,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤质和,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后稚字,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饲宿,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厦酬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瘫想。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仗阅。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖国夜,靈堂內(nèi)的尸體忽然破棺而出减噪,到底是詐尸還是另有隱情,我是刑警寧澤车吹,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布筹裕,位于F島的核電站,受9級(jí)特大地震影響窄驹,放射性物質(zhì)發(fā)生泄漏朝卒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一乐埠、第九天 我趴在偏房一處隱蔽的房頂上張望抗斤。 院中可真熱鬧,春花似錦丈咐、人聲如沸豪治。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽负拟。三九已至,卻和暖如春歹河,著一層夾襖步出監(jiān)牢的瞬間掩浙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绰垂。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像谬墙,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子经备,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉拭抬,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,726評(píng)論 0 9
  • 對(duì)于從事 iOS 開發(fā)人員來說,所有的人都會(huì)答出【runtime 是運(yùn)行時(shí)】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,726評(píng)論 7 64
  • Runtime是什么 Runtime 又叫運(yùn)行時(shí)侵蒙,是一套底層的 C 語言 API造虎,其為 iOS 內(nèi)部的核心之一,我...
    SuAdrenine閱讀 879評(píng)論 0 3
  • 轉(zhuǎn)載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 736評(píng)論 0 2
  • 濟(jì)南市2016年兩次力壓首都北京纷闺,勇登全國“堵城”排行榜第一名算凿,成為全國最擁堵的城市份蝴。“擁堵”成了這座省會(huì)城市的新...
    云淡風(fēng)輕任平生閱讀 528評(píng)論 0 1