iOS中runtime機制

?什么是runtime朽肥?

runtime就是運行時,因為Objective-C是一門動態(tài)語言擎浴,它將很多靜態(tài)語言在編譯和鏈接時期做的事放到了運行時來處理虱疏。也就是說只有編譯器是不夠的,還需要一個運行時系統(tǒng) (runtime system) 來執(zhí)行編譯后的代碼魂拦。對于Objective-C來說毛仪,這個運行時系統(tǒng)就像一個操作系統(tǒng)一樣:它讓所有的工作可以正常的運行。這個運行時系統(tǒng)即Objc Runtime芯勘。Objc Runtime其實是一個Runtime庫箱靴,它基本上是用C和匯編寫的,這個庫使得C語言有了面向?qū)ο蟮哪芰Α?/p>

Runtime庫主要做下面兩件事:

封裝:在這個庫中荷愕,對象可以用C語言中的結(jié)構(gòu)體表示衡怀,而方法可以用C函數(shù)來實現(xiàn),另外再加上了一些額外的特性安疗。這些結(jié)構(gòu)體和函數(shù)被runtime函數(shù)封裝后抛杨,我們就可以在程序運行時創(chuàng)建,檢查荐类,修改類怖现、對象和它們的方法了。

找出方法的最終執(zhí)行代碼:當(dāng)程序執(zhí)行[object doSomething]時玉罐,會向消息接收者(object)發(fā)送一條消息(doSomething)屈嗤,runtime會根據(jù)消息接收者是否能響應(yīng)該消息而做出不同的反應(yīng)。OC中的方法調(diào)用:[receiver doSomething]; 在運行時都會轉(zhuǎn)換成消息發(fā)送代碼:objc_msgSend(receiver, @selector(doSomething));吊输,其中饶号,receiver是消息的接收者,@selector(doSomething)是方法的實現(xiàn)璧亚。

runtime的使用場景

1.在程序運行過程中, 動態(tài)創(chuàng)建一個類(比如KVO的底層實現(xiàn))

2.在程序運行過程中, 動態(tài)地為某個類添加屬性\方法, 修改屬性值\方法(Objective-C中的Category無法向既有的類添加屬性, 因此可以使用runtime的關(guān)聯(lián)對象(associated objects)來實現(xiàn).)

3.遍歷一個類的所有成員變量(屬性)\所有方法

4. 給一個類添加方法

5.Method Swizzling(方法調(diào)換:通過修改一個已存在類的方法, 來實現(xiàn)方法替換是比較常用的runtime技巧)

簡單介紹一下KVO的實現(xiàn)原理:

當(dāng)設(shè)置一個類為觀察對象時讨韭,系統(tǒng)會動態(tài)地創(chuàng)建一個新的類脂信,這個新的類繼承自被觀察對象的類癣蟋,還重寫了基類被觀察屬性的setter方法。派生類在被重寫的setter方法中實現(xiàn)真正的通知機制狰闪。最后疯搅,系統(tǒng)將這個對象的isa指針指向這個新創(chuàng)建的派生類,這樣埋泵,被觀察對象就變成了新創(chuàng)建的派生類的實例幔欧。(注:runtime中罪治,對象的isa指針指向該對象所屬的類,類的isa指針指向該類的metaclass礁蔗。有關(guān)OC的對象觉义、類對象、元類對象metaclass object和isa指針浴井,請戳這里詳細了解)晒骇。同時,新的派生類還重寫了dealloc方法(removeObserver)磺浙。

動態(tài)添加屬性

#import ?<UIKit/UIKit.h>

@interface UIButton (FinshClick)

@property(nonatomic,copy)void(^FinshClickBlock)(UIButton*); // 給button點擊回調(diào)屬性

@property(nonatomic,assign)floatclickCount;//給button添加點擊次數(shù)屬性

@end

#import"UIButton+FinshClick.h"

#import <objc/runtime.h> ?// 導(dǎo)入runtime框架

@implementation UIButton (FinshClick)

static char FinshClickBlockKey;

static char clickCountKey;

@dynamic FinshClickBlock;

@dynamic clickCount;

//@synthesize是默認的聲明洪囤,意思是編譯器在編譯階段自動為你的屬性生成setter與getter;而@dynamic則告訴編譯器撕氧,別慌瘤缩,小子,編譯階段不用為我生成setter與getter伦泥,在runtime我已經(jīng)自己實現(xiàn)了setter與getter剥啤。此處我們選擇@dynamic。

// FinshClickBlock的setter方法

- (void)setFinshClickBlock:(void(^)(UIButton*))FinshClickBlock

{

objc_setAssociatedObject(self, &FinshClickBlockKey, FinshClickBlock,OBJC_ASSOCIATION_RETAIN_NONATOMIC);

//使用runtime實現(xiàn)setter方法奄喂。參數(shù)含義:1.所關(guān)聯(lián)的對象铐殃、2.分配地址、3.屬性值跨新、4.這里的policy跟屬性聲明中的retain富腊、assign、copy是一樣的

[selfaddTarget:selfaction:@selector(click)forControlEvents:UIControlEventTouchUpInside];//給button添加點擊方法

}

//FinshClickBlock的getter方法

- (void(^)(UIButton*))FinshClickBlock

{

returnobjc_getAssociatedObject(self, &FinshClickBlockKey);//

//使用runtime實現(xiàn)getter方法域帐。參數(shù)含義:1.關(guān)聯(lián)對象2.分配地址

}

//點擊實現(xiàn)

- (void)click {

if(self.FinshClickBlock) {

self.clickCount++;

self.FinshClickBlock(self);

}

}

//點擊次數(shù)setter方法

- (void)setClickCount:(float)clickCount

{

objc_setAssociatedObject(self,&clickCountKey,@(clickCount),OBJC_ASSOCIATION_ASSIGN);

}

// getter方法

- (float)clickCount

{

return[objc_getAssociatedObject(self,&clickCountKey)floatValue];

}

@end

#import"ViewController.h"

#import"UIButton+FinshClick.h"

@interface ViewController()

@property(weak,nonatomic)IBOutlet UIButton*btn;

@end

@implementation ViewController

- (void)viewDidLoad {

[superviewDidLoad];

self.btn.FinshClickBlock= ^(UIButton*button) {

NSLog(@"%f",self.btn.clickCount);

};

動態(tài)添加方法

#import"Student.h"

#import <objc/message.h>

void eat(id self,SEL sel) {

NSLog(@"----------eat");

}

+(BOOL)resolveInstanceMethod:(SEL)sel

{

if([NSStringFromSelector(sel)isEqualToString:@"eat"]) {

class_addMethod(self, sel, (IMP)eat,"v@:");

returnYES;

}

return[superresolveInstanceMethod:sel];

}

@end

- (void)viewDidLoad {

[superviewDidLoad];

Student*stu = [[Studentalloc]init];

[stu performSelector:@selector(eat)];

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赘被,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子肖揣,更是在濱河造成了極大的恐慌民假,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龙优,死亡現(xiàn)場離奇詭異羊异,居然都是意外死亡,警方通過查閱死者的電腦和手機彤断,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門野舶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宰衙,你說我怎么就攤上這事平道。” “怎么了供炼?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵一屋,是天一觀的道長窘疮。 經(jīng)常有香客問我,道長冀墨,這世上最難降的妖魔是什么闸衫? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮诽嘉,結(jié)果婚禮上楚堤,老公的妹妹穿的比我還像新娘。我一直安慰自己含懊,他們只是感情好身冬,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著岔乔,像睡著了一般酥筝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雏门,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天嘿歌,我揣著相機與錄音,去河邊找鬼茁影。 笑死宙帝,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的募闲。 我是一名探鬼主播步脓,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼浩螺!你這毒婦竟也來了靴患?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤要出,失蹤者是張志新(化名)和其女友劉穎鸳君,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體患蹂,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡或颊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了传于。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片囱挑。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖格了,靈堂內(nèi)的尸體忽然破棺而出看铆,到底是詐尸還是另有隱情徽鼎,我是刑警寧澤盛末,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布弹惦,位于F島的核電站,受9級特大地震影響悄但,放射性物質(zhì)發(fā)生泄漏棠隐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一檐嚣、第九天 我趴在偏房一處隱蔽的房頂上張望助泽。 院中可真熱鬧,春花似錦嚎京、人聲如沸嗡贺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诫睬。三九已至,卻和暖如春帕涌,著一層夾襖步出監(jiān)牢的瞬間摄凡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工蚓曼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留亲澡,地道東北人。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓纫版,卻偏偏與公主長得像床绪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子其弊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

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