runtime解析及常用方法

什么是runtime?

  • runtime直譯:運(yùn)行時機(jī)制;OC發(fā)送消息的本質(zhì),就是 runtime去調(diào)用蘋果底層的一些函數(shù);

  • C語言在編譯時,就知道該調(diào)用那些方法, 能成功調(diào)用嗎;

  • 基于runtime的OC語言, 在編譯階段只要方法有聲明,就不會報錯;在運(yùn)行時才會檢測到底有沒有方法,該調(diào)用哪個方法;

查看runtime底層實(shí)現(xiàn):

  • 在終端編譯文件 clang -rewrite-objc main.m Person.m 查看最終生成代碼
    // 測試代碼
    Person *p = [Person alloc];
    p = [p init];

生成cpp文件,找到對應(yīng)代碼:


    Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc"));

    p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("init"));

解析: 簡化代碼后,其實(shí)runtime底層也就是調(diào)用蘋果封裝的方法而已

   (Person *(*)(id, SEL))(void *) 強(qiáng)制類型轉(zhuǎn)換, 把objc_msgSend轉(zhuǎn)換成有返回值(Person *), 兩個參數(shù)(id, SEL)的指向函數(shù)的指針;故可去掉,簡化代碼如下:

    Person *p = objc_msgSend([Person class], @selector(alloc));
    p = objc_msgSend(p, @selector(init));

由于蘋果不推薦我們使用其底層的runtime, 但是有時一些功能只能由runtime實(shí)現(xiàn),故我們首先配置Xcode(以XCocde7為例)
  • 導(dǎo)入頭文件#import <objc/message.h>
  • 配置文件 : 項(xiàng)目 ---> BuildSetting ----> msg
Snip20160327_1.png

runtime常用方法:

  • 動態(tài)添加方法
    • 開發(fā)使用場景:如果一個類方法非常多融师,加載類到內(nèi)存的時候要給每個方法生成相應(yīng)映射表侥蒙,非常耗費(fèi)內(nèi)存資源;這時候可以實(shí)現(xiàn)用動態(tài)給某個類添加方法.
    • 比如某應(yīng)用的VIP用戶才能使用一些功能.

代碼實(shí)現(xiàn):

@implementation Person

// 定義函數(shù)
// 默認(rèn)OC方法都有兩個隱式參數(shù),self,_cmd
void run(id self, SEL _cmd) {
    NSLog(@"run");
}

// 只要調(diào)用沒有實(shí)現(xiàn)的方法 就會來到方法
// 作用:去解決沒有實(shí)現(xiàn)方法,動態(tài)添加方法
+ (BOOL)resolveInstanceMethod:(SEL)sel{

    if (sel == @selector(run)) {
        // 添加方法
        class_addMethod(self, sel, (IMP)run, nil);

        return YES;
    }

    return [super resolveInstanceMethod:sel];
}

@end

方法解析:
    // 添加方法到類
    class_addMethod(__unsafe_unretained Class cls, SEL name, IMP imp, const char *types);

        class:給誰添加方法
        SEL:添加哪個方法
        IMP:方法實(shí)現(xiàn),函數(shù)入口,傳入函數(shù)名
        type:方法類型 默認(rèn)nil即可

然后我們利用performSelector方法調(diào)用一個沒有實(shí)現(xiàn)的方法:

    [p performSelector:@selector(run)]

    // 會自動執(zhí)行上面方法添加一個動態(tài)方法run
    // 打印輸出:run

tips:

// 沒有實(shí)現(xiàn)對象方法時,調(diào)用該方法
+(BOOL)resolveInstanceMethod:(SEL)sel {

    // 添加方法
}

// 沒有實(shí)現(xiàn)類方法時, 調(diào)用該方法
+(BOOL)resolveClassMethod:(SEL)sel {

    // 添加方法
}
  • 交換兩個方法的實(shí)現(xiàn)
  • 需求:想要在調(diào)用imageNamed加載圖片時,提示是否加載成功,
  • 特別是大項(xiàng)目時,不希望更改系統(tǒng)方法(得改好多代碼, 工作量忒大...)

此時可以使用runtime的動態(tài)交換方法來實(shí)現(xiàn)功能:

  • 新建一個UIImage的分類

  • 在分類中添加一個該功能的方法;(注意別覆蓋系統(tǒng)方法)

  • 在+load方法中實(shí)現(xiàn)方法的交換

#import "UIImage+image.h"
#import <objc/message.h>

@implementation UIImage (image)
+(void)load {

    // 1.0 獲取方法
    Method abel_imageNamed = class_getClassMethod(self, @selector(abel_imageNamed:));
    Method imageNamed = class_getClassMethod(self, @selector(imageNamed:));

    // 2.0 交換方法的實(shí)現(xiàn)
    method_exchangeImplementations(abel_imageNamed, imageNamed);

}

// 添加該功能方法
+ (UIImage *)abel_imageNamed:(NSString *)name
{
    // 調(diào)用系統(tǒng)方法
    UIImage *image = [self abel_imageNamed:name];

    // 添加功能
    if (image == nil) {

        NSLog(@"加載失敗");
    }
    return image;
}

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末幔托,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子践盼,更是在濱河造成了極大的恐慌,老刑警劉巖鄙币,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件傅物,死亡現(xiàn)場離奇詭異,居然都是意外死亡耍贾,警方通過查閱死者的電腦和手機(jī)阅爽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荐开,“玉大人付翁,你說我怎么就攤上這事』翁” “怎么了百侧?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長能扒。 經(jīng)常有香客問我佣渴,道長,這世上最難降的妖魔是什么初斑? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任辛润,我火速辦了婚禮,結(jié)果婚禮上见秤,老公的妹妹穿的比我還像新娘砂竖。我一直安慰自己,他們只是感情好鹃答,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布乎澄。 她就那樣靜靜地躺著,像睡著了一般测摔。 火紅的嫁衣襯著肌膚如雪置济。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天锋八,我揣著相機(jī)與錄音浙于,去河邊找鬼。 笑死挟纱,一個胖子當(dāng)著我的面吹牛羞酗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播樊销,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼整慎,長吁一口氣:“原來是場噩夢啊……” “哼脏款!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起裤园,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤撤师,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拧揽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剃盾,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年淤袜,在試婚紗的時候發(fā)現(xiàn)自己被綠了痒谴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡铡羡,死狀恐怖积蔚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烦周,我是刑警寧澤尽爆,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站读慎,受9級特大地震影響漱贱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜夭委,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一幅狮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧株灸,春花似錦崇摄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幅恋。三九已至杏死,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捆交,已是汗流浹背淑翼。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留品追,地道東北人玄括。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像肉瓦,于是被迫代替她去往敵國和親遭京。 傳聞我的和親對象是個殘疾皇子胃惜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評論 25 707
  • 對于從事 iOS 開發(fā)人員來說,所有的人都會答出【runtime 是運(yùn)行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,721評論 7 64
  • 1.今天早上六點(diǎn)二十才起床哪雕,洗漱完畢船殉,開始做早餐,七點(diǎn)喊小兒起床斯嚎,被他怒吼一聲禁言利虫,等他出來時已經(jīng)是七點(diǎn)一刻了,膽...
    彩霞滿天q2閱讀 187評論 0 0
  • 1 如果你走在大街上堡僻,看著一個中年女人糠惫,一手插著兜,一手拿著煙钉疫,昂著頭走路硼讽,那一定是我的母親。 母親從小命運(yùn)多舛牲阁,...
    可可熊Q閱讀 352評論 0 3
  • 早晨:遇見一個剛打完點(diǎn)滴手上膠布還沒揭就在車上看書的小弟弟理郑,覺得找到了學(xué)習(xí)不好的原因。 下午:遇見一個可愛的老奶奶...
    四娘jamie閱讀 266評論 0 1