Runtime簡單用法

runtime簡稱運行時原朝,也就是在運行時候的一些機制梳虽。對于oc函數(shù),屬于動態(tài)調(diào)用過程哥捕,在編譯的時候并不能決定真正調(diào)用哪些函數(shù),只有在真正運行的時候才會根據(jù)函數(shù)的名稱找到對應的函數(shù)來調(diào)用嘉熊。

交換兩個方法的實現(xiàn)遥赚,攔截系統(tǒng)自帶的方法調(diào)用功能

導入<objc/runtime.h>
獲得某個類的類方法:

Method class_getClassMethod(Class cls , SEL name)

獲得某個類的實例對象方法

Method class_getInstanceMethod(Class cls , SEL name)

交換兩個方法的實現(xiàn)

void method_exchangeImplementations(Method m1 , Method m2)

下面舉個例子:
1.方法簡單的交換
創(chuàng)建一個Person類,類中實現(xiàn)以下兩個類方法阐肤,并在.h 文件中聲明

+ (void)run { 
      NSLog(@"跑");
}
+ (void)study { 
      NSLog(@"學習");
}

在viewcontroller中引用凫佛,導入<objc/runtime.h>讲坎,通過runtime 實現(xiàn)方法交換,類方法用class_getClassMethod愧薛,對象方法用class_getInstanceMethod

// 獲取兩個類的類方法
Method m1 = class_getClassMethod([Person class], @selector(run));
Method m2 = class_getClassMethod([Person class], @selector(study));
// 開始交換方法實現(xiàn)
method_exchangeImplementations(m1, m2);
// 交換后晨炕,先打印學習,再打印跑
[Person run];
[Person study];

上面可以看出毫炉,交換了方法的實現(xiàn)瓮栗。

2.攔截系統(tǒng)方法
一般是寫個類的分類,然后在分類中重寫該類的一個方法瞄勾,最后在load方法中交換一下自定義的方法和系統(tǒng)的方法费奸。當然了,自定義方法中最后一定要再調(diào)用一下系統(tǒng)的方法进陡。
1.為UIImage建一個分類(UIImage+Category)
2愿阐、在分類中實現(xiàn)一個自定義方法,方法中寫要在系統(tǒng)方法中加入的語句四濒,比如版本判斷

+ (UIImage *)junjie_imageNamed:(NSString *)name {
 double version = [[UIDevice currentDevice].systemVersion doubleValue]; 
if (version >= 7.0) { 
// 如果系統(tǒng)版本是7.0以上换况,使用另外一套文件名結(jié)尾是‘_os7’的扁平化圖片 
name = [name stringByAppendingString:@"_os7"]; 
} 
return [UIImage junjie_imageNamed:name];}

3、分類中重寫UIImage的load方法盗蟆,實現(xiàn)方法的交換

+(void)load {
 // 獲取兩個類的類方法 
Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:)); 
Method m2 = class_getClassMethod([UIImage class], @selector(junjie_imageNamed:)); 
// 開始交換方法實現(xiàn) 
method_exchangeImplementations(m1, m2);
}

分類中設置屬性,給任何一個對象設置屬性

在分類中舒裤,是沒有屬性的喳资,也就是說,你在分類的.h文件中@property只能創(chuàng)建get和set方法的聲明腾供,但無法生成屬性變量仆邓,雖然在分類的.m中我們可以設置個全局變量,代碼如下:

NSString *_ssex;

- (NSString *)Mysex {
    return _ssex;
}

- (void)setMysex:(NSString *)Mysex {
    _ssex = Mysex;
}

在viewdidload中

 UIImage *image = [UIImage new];
    image.Mysex = @"男生";
    
    _MyImage = [UIImage new];
    _MyImage.Mysex = @"女生";
    
    NSLog(@"image == %@, _MyImage == %@", image.Mysex, _MyImage.Mysex);

會發(fā)現(xiàn)打印結(jié)果都是女生伴鳖,這是因為全局變量程序整個執(zhí)行過程中內(nèi)存中只有一份节值,我們創(chuàng)建多個對象修改其屬性值都會修改同一個變量,這樣就無法保證像屬性一樣每個對象都擁有其自己的屬性值榜聂。所以這時候就需要借用runtime為分類添加屬性的功能了搞疗。
還是在剛才的分類中,代碼如下:

NSString *_ssex;
- (NSString *)Mysex {
//    return _ssex;
    return objc_getAssociatedObject(self, &_ssex);
}
- (void)setMysex:(NSString *)Mysex {
//    _ssex = Mysex;
    //將某個值跟某個對象關(guān)聯(lián)起來须肆,將某個值存儲到某個對象中
    objc_setAssociatedObject(self, &_ssex, Mysex, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

運行viewdidload匿乃,發(fā)現(xiàn)第一個輸出男生,第二個輸出女生了豌汇。
方法解惑:

void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy)

set方法幢炸,將值value 跟對象object 關(guān)聯(lián)起來(將值value 存儲到對象object 中)
參數(shù) object:給哪個對象設置屬性
參數(shù) key:一個屬性對應一個Key,將來可以通過key取出這個存儲的值拒贱,key 可以是任何類型:double宛徊、int 等佛嬉,以后建議用char 可以節(jié)省字節(jié),我這里不改了
參數(shù) value:給屬性設置的值
參數(shù)policy:存儲策略 (assign 闸天、copy 暖呕、 retain就是strong)

id objc_getAssociatedObject(id object , const void *key)

利用參數(shù)key將對象object中存儲的對應值取出來。

獲得一個類的所有成員變量号枕,并對其操作缰揪。

Ivar *ivars =  class_copyIvarList(Class cls , unsigned int *outCount)

ivars:返回值,存放所有獲取到的屬性葱淳。
cls:哪個類钝腺。
outCount:放一個接收值的地址,用來存放屬性的個數(shù)赞厕。

    unsigned int outCount = 0;
    Ivar *ivars = class_copyIvarList([Person class], &outCount);
    NSLog(@"count == %d", outCount);
    for (int i = 0; i < outCount; i++) {
        Ivar ivar = ivars[i]; //取出i位置對應的成員變量
        const char *name = ivar_getName(ivar);
        const char *type = ivar_getTypeEncoding(ivar);
        NSLog(@"成員變量名:%s, 成員變量類型:%s", name, type);
    }
    free(ivars); //釋放內(nèi)存

通過上面的代碼我們可以獲取到自定義類中所有成員變量的名字和類型艳狐。
但是有啥用啊。皿桑。毫目。網(wǎng)上有的作者就這么一提,獲取到又不能操作有什么用诲侮。后來發(fā)現(xiàn)了這個方法object_setIvar镀虐,他可以設置值,接下來我來教大家怎么用沟绪。
比如說我們之前在Person類中定義了私有成員變量_name刮便,NSString類型的。
在Person類中定義兩個方法绽慈,如下:

- (void)getName:(NSString *)junjie {
    _name = junjie;
    NSLog(@"他的名字叫:%@",_name);
}

- (void)printfName {
    NSLog(@"我的name is %@", _name);
}

這兩個方法用到了私有變量_name
在viewdidload中恨旱,作如下操作

    unsigned int outCount;
    Ivar *IvarArray = class_copyIvarList([Person class], &outCount);
    [person getName:@"feifei"];
    [person printfName];
    //操作后
    object_setIvar(person, IvarArray[1], @"123");// 我在這里是第二個元素
    [person printfName];

打印結(jié)果如下:


Paste_Image.png

可見我們在外面利用runtime,直接將私有變量的值給修改了坝疼,是不是感覺很吊搜贤。。钝凶。
當然了仪芒,有set就有g(shù)et,object_getIvar方法腿椎,他可以獲取到上面set設置的值(一般出現(xiàn)在一個類中)桌硫,有興趣的童鞋可以去研究研究。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啃炸,一起剝皮案震驚了整個濱河市铆隘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌南用,老刑警劉巖膀钠,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掏湾,死亡現(xiàn)場離奇詭異,居然都是意外死亡肿嘲,警方通過查閱死者的電腦和手機融击,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雳窟,“玉大人尊浪,你說我怎么就攤上這事》饩龋” “怎么了拇涤?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長誉结。 經(jīng)常有香客問我鹅士,道長,這世上最難降的妖魔是什么惩坑? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任掉盅,我火速辦了婚禮,結(jié)果婚禮上以舒,老公的妹妹穿的比我還像新娘趾痘。我一直安慰自己,他們只是感情好蔓钟,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布扼脐。 她就那樣靜靜地躺著,像睡著了一般奋刽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上艰赞,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天佣谐,我揣著相機與錄音,去河邊找鬼方妖。 笑死狭魂,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的党觅。 我是一名探鬼主播雌澄,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼杯瞻!你這毒婦竟也來了镐牺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤魁莉,失蹤者是張志新(化名)和其女友劉穎睬涧,沒想到半個月后募胃,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡畦浓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年痹束,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讶请。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡祷嘶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出夺溢,到底是詐尸還是另有隱情论巍,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布企垦,位于F島的核電站环壤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏钞诡。R本人自食惡果不足惜郑现,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荧降。 院中可真熱鬧接箫,春花似錦、人聲如沸朵诫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剪返。三九已至废累,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脱盲,已是汗流浹背邑滨。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钱反,地道東北人掖看。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像面哥,于是被迫代替她去往敵國和親哎壳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉尚卫,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,686評論 0 9
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,548評論 33 466
  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,913評論 6 13
  • 對于從事 iOS 開發(fā)人員來說归榕,所有的人都會答出【runtime 是運行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,700評論 7 64
  • 人生之路,哪有不迷茫焕毫;人生之路蹲坷,也都不一樣驶乾。一句簡單的話語,就可以撩人心扉循签,沁人心脾级乐。是否在做,是否在看县匠,只有內(nèi)心...
    牛人經(jīng)濟閱讀 1,083評論 2 5