iOS開發(fā):runtime原理簡單分析和基本使用場景

一:rumtime原理簡單分析

runtime是運行時庫(Runtime Library)商虐,也簡稱運行時何荚。

它是一個主要是C和匯編寫的庫,對C進行了特殊的處理剃毒,將結(jié)構(gòu)體視為對象,將函數(shù)視為方法搂赋,使得C有了面向?qū)ο蟮哪芰ψ阜В瑥亩艅?chuàng)造了Objective-C。

這點也可以看出脑奠,C是編譯時語言基公,而OC是動態(tài)運行時語言,所以在編譯階段宋欺,盡管OC中的方法沒有實現(xiàn)也不會報錯轰豆,而C會報錯。

在運行時齿诞,OC語言才進行方法的處理酸休,比如講[person eat];轉(zhuǎn)換為objc_msgSend(person, @selector(eat));然后通過person的isa指針找到person對應(yīng)的class,在class中先去cache中通過SEL方法選擇器查找對應(yīng)的method掌挚,若緩存中未找到雨席,再去methodList查找,若還未找到吠式,便去父類中查找陡厘,如果這個過程中找到了該方法,便會自動將該方法加入cache中特占,方便下一次的查找糙置,并且,編譯器開始執(zhí)行找到的這個函數(shù)是目。

上面這段文字可以片面的理解runtime的消息機制谤饭,消息機制是runtime最主要的機制,如果要在代碼中使用懊纳,需要導(dǎo)入揉抵。

二:runtime 的基本使用場景

首先,對objc_class結(jié)構(gòu)體的內(nèi)容做個簡單的說明:

[objc]view plaincopy

structobjc_class?{

Class?isa??OBJC_ISA_AVAILABILITY;

#if?!__OBJC2__

Class?super_class//指向父類

constcharchar*name//類名

longversion//類的版本信息(默認是0嗤疯,class_setVersion,clss_getVersion可set和get)

longinfo//類的標識信息

longinstance_size//該類的實例變量size

structobjc_ivar_list*ivars//用于存儲每個成員變量的地址

structobjc_method_list**methodLists//與info的標識信息有關(guān)冤今,如CLS_CLASS存儲實例方法,CLS_META存儲靜態(tài)方法

structobjc_cache*cache//指向最近使用方法的指針茂缚,它的作用是提升效率戏罢,可以不嚴密的理解為緩存

structobjc_protocol_list*protocols//存儲協(xié)議列表

#endif

}?OBJC2_UNAVAILABLE;

在實際開發(fā)中屋谭,runtime最常用的場景就是交換方法、歸檔龟糕、字典轉(zhuǎn)模型桐磁、動態(tài)生成屬性方法、添加類方法等

(一)runtime交換方法

1.創(chuàng)建一個類的分類

2.導(dǎo)入

3.實現(xiàn)交換并且自定義方法

[objc]view plaincopy

//由于交換方法我們希望在工程運行期間只執(zhí)行一次讲岁,所以通常寫在load里面

+?(void)load?{

Method?imageMethodNamed?=?class_getClassMethod(self,@selector(imageNamed:));

Method?myImageMethodNamed?=?class_getClassMethod(self,@selector(myImageNamed:));

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

method_exchangeImplementations(myImageMethodNamed,imageMethodNamed);

}

+?(instancetype)customImageNamed:(NSString*)name?{

//實際調(diào)用的是imageNamed:

UIImage*image?=?[UIImagecustomImageNamed:name];

//*此處為自定義配置*

returnimage;

}

(二)runtime動態(tài)生成getter我擂、setter

由于在類目中添加屬性不自動生成setter和getter方法,如果在.m文件中使用@dynamic配置起來就較為繁瑣催首,如果一定要在類目中添加屬性扶踊,我們可以使用runtime關(guān)聯(lián)方法,簡單方便郎任。

比如在類目.h文件中聲明了score屬性,在.m文件中如下實現(xiàn):

[objc]view plaincopy

voidvoid*key;

-?(void)setScore:(float)score?{

//關(guān)聯(lián)引用

/**

*??1.給哪個對象屬性進行關(guān)聯(lián)

*??2.用來保存?zhèn)魅氲闹档闹羔?用于get方法獲取值)

*??3.傳入的值(注意是對象類型)

*??4.關(guān)聯(lián)引用的策略(這個根據(jù)屬性添加的修飾而定)

*/

objc_setAssociatedObject(self,?key,?@(score),?OBJC_ASSOCIATION_ASSIGN);

}

-?(float)score?{

idscore?=?objc_getAssociatedObject(self,?key);

return[scorefloatValue];

}

(三)runtime歸檔备籽、解檔

歸解檔可以用kvc模式進行操作舶治,但是如果屬性過多的話,這樣就顯得極為繁瑣而且容易出錯车猬,所以用runtime實現(xiàn)更為的科學(xué)和簡潔霉猛。

[objc]view plaincopy

//歸檔

-?(void)encodeWithCoder:(NSCoder*)aCoder?{

//獲取某個類的所有成員變量

unsignedintcount?=0;

Ivar*ivarList?=?class_copyIvarList([selfclass],?&count);

//歸檔

for(inti?=0;?i?<?count;?i?++)?{

Ivar?aIvar?=?ivarList[i];

//獲取成員變量的名稱

constcharchar*iVarName?=?ivar_getName(aIvar);

idvalue?=?[selfvalueForKey:[NSStringstringWithUTF8String:iVarName]];

if(!value)?{

}else{

[aCoderencodeObject:valueforKey:[NSStringstringWithUTF8String:iVarName]];

}

}

}

//解檔

-?(instancetype)initWithCoder:(NSCoder*)aDecoder?{

if(self=?[superinit])?{

unsignedintcount?=0;

Ivar*ivarList?=?class_copyIvarList([selfclass],?&count);

for(inti?=0;?i?<?count;?i?++)?{

Ivar?aIvar?=?ivarList[i];

constcharchar*name?=?ivar_getName(aIvar);

idvalue?=?[aDecoderdecodeObjectForKey:[NSStringstringWithUTF8String:name]];

if(!value)?{

}else{

[selfsetValue:valueforKey:[NSStringstringWithUTF8String:name]];

}

}

}

returnself;

}

(四)runtime字典轉(zhuǎn)模型

這里需要注意的是,該方法只適用于字典的鍵和模型的屬性一一對應(yīng)的情況珠闰,如果要處理不一一對應(yīng)的情況惜浅,最簡單的解決方法是使用三方。

[objc]view plaincopy

+?(instancetype)modelWithDictionary:(NSDictionary*)dic?{

Student*aStudent?=?[Studentnew];

unsignedintcount?=0;

objc_property_t*propertyList?=?class_copyPropertyList([selfclass],?&count);

for(inti?=0;?i?<?count;?i?++)?{

objc_property_t?aProperty?=?propertyList[i];

//獲取屬性名

constcharchar*name?=?property_getName(aProperty);

idvalue?=?dic[[NSStringstringWithUTF8String:name]];

if(!value)?{

}else{

//使用kvc給屬性賦值

[aStudentsetValue:valueforKey:[NSStringstringWithUTF8String:name]];

}

}

returnaStudent;

}

(五)runtime添加類方法

[objc]view plaincopy

voidstudy(idreccevier,SELsel)?{

}

//?如果調(diào)用的方法沒有實現(xiàn)伏嗜,就會走這個方法

+?(BOOL)resolveInstanceMethod:(SEL)sel?{

if(sel?==@selector(study))?{

class_addMethod(self,@selector(study),?(IMP)study,"v@:");

}

return[superresolveInstanceMethod:sel];

}

值得注意的是坛悉,這個方法是在運行時動態(tài)調(diào)用的,所以編譯的時候會有警告承绸。

原文地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末裸影,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子军熏,更是在濱河造成了極大的恐慌轩猩,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荡澎,死亡現(xiàn)場離奇詭異均践,居然都是意外死亡,警方通過查閱死者的電腦和手機摩幔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門彤委,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人热鞍,你說我怎么就攤上這事葫慎∠纬梗” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵偷办,是天一觀的道長艰额。 經(jīng)常有香客問我,道長椒涯,這世上最難降的妖魔是什么柄沮? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮废岂,結(jié)果婚禮上祖搓,老公的妹妹穿的比我還像新娘。我一直安慰自己湖苞,他們只是感情好拯欧,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著财骨,像睡著了一般镐作。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隆箩,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天该贾,我揣著相機與錄音,去河邊找鬼捌臊。 笑死杨蛋,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的理澎。 我是一名探鬼主播逞力,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼矾端!你這毒婦竟也來了掏击?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤秩铆,失蹤者是張志新(化名)和其女友劉穎砚亭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體殴玛,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡捅膘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了滚粟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寻仗。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖凡壤,靈堂內(nèi)的尸體忽然破棺而出署尤,到底是詐尸還是另有隱情耙替,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布曹体,位于F島的核電站俗扇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏箕别。R本人自食惡果不足惜铜幽,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望串稀。 院中可真熱鬧除抛,春花似錦、人聲如沸母截。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽微酬。三九已至绘趋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間颗管,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工滓走, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留垦江,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓搅方,卻偏偏與公主長得像比吭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子姨涡,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉衩藤,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,679評論 0 9
  • 對于從事 iOS 開發(fā)人員來說,所有的人都會答出【runtime 是運行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,697評論 7 64
  • 本文轉(zhuǎn)載自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex閱讀 748評論 0 1
  • 前言 runtime其實在我們?nèi)粘i_發(fā)過程中很少使用到涛漂,尤其是像我現(xiàn)在比較初級的程序猿就更用不到了赏表。但是去面試很多...
    WolfTin閱讀 611評論 0 2
  • ??豬閱讀 121評論 0 0