OC筆記之Runtime

1.什么是Runtime?

OC是一門動(dòng)態(tài)語言,它將很多操作推遲到運(yùn)行時(shí)再進(jìn)行,所以光有編譯器是不夠,還需要一個(gè)運(yùn)行時(shí)系統(tǒng),而Runtime就是OC的運(yùn)行時(shí)機(jī)制,它是一套由C、C++、匯編編寫的API,封裝了很多動(dòng)態(tài)性相關(guān)的函數(shù)。在我們平時(shí)編寫的OC代碼,在程序運(yùn)行過程中,其實(shí)最終都轉(zhuǎn)成了Runtime的C語言方法。

2.方法的本質(zhì)是什么?runtime的消息機(jī)制

方法的本質(zhì)就是發(fā)送消息。
發(fā)送消息的詳細(xì)流程:方法調(diào)用轉(zhuǎn)化為 objc_msgSend(id self, SEL _cmd, ...)

  • 首先會(huì)進(jìn)行匯編快速查找:objc_object(對(duì)象) --> isa_t(isa) -->objc_class(類對(duì)象) --> cache_t(cache) --> buckets<struct bucket_t *>bucket_t中存儲(chǔ)了_sel_imp;cache_t使用了哈希算法,解決哈希沖突使用了開放尋址法,將cache_t結(jié)構(gòu)體中的masksel進(jìn)行與運(yùn)算找到對(duì)應(yīng)的imp
  • 慢速查找:objc_class(類對(duì)象) --> objc_method_list(methodLists)-->objc_method遍歷查找,遞歸自己和父類查找方法lookUpImpOrForward
  • 查找不到消息,進(jìn)行動(dòng)態(tài)方法解析resolveInstanceMethod,方法內(nèi)部會(huì)檢查對(duì)象是否實(shí)現(xiàn)了+(BOOL)resolveInstanceMethod:(SEL)sel,因此可在此方法中為sel添加一個(gè)imp,此方法返回YES/NO只影響debug日志
  • 消息快速轉(zhuǎn)發(fā):- (id)forwardingTargetForSelector:(SEL)aSelector提供一個(gè)消息接收者對(duì)象
  • 消息慢速轉(zhuǎn)發(fā):消息簽名- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector- (void)forwardInvocation:(NSInvocation *)anInvocation
  • 若消息最終都沒有被處理會(huì)報(bào)錯(cuò)unrecoginzed selector send to instance xxx
3.SEL是什么?IMP是什么??jī)烧哂惺裁绰?lián)系?
  • SEL是方法編號(hào),即方法名稱,在dyld加載鏡像時(shí),通過map_images-->map_images_nolock-->_read_images方法加載到內(nèi)存的表中,而IMP是函數(shù)實(shí)現(xiàn)的指針
4.runtime的應(yīng)用場(chǎng)景
  • 用于方法交換 MethodSwizzling,改變已存在的selector的實(shí)現(xiàn),例如改變基類的方法實(shí)現(xiàn)app的統(tǒng)一配置,這里一般是在 +load方法中,且為了保證方法交換只執(zhí)行一次使用dispatch_once進(jìn)行包裝
  • 實(shí)現(xiàn)給分類添加屬性,尤其是系統(tǒng)類,利用Runtime的關(guān)聯(lián)對(duì)象可為分類添加新的屬性
  • 實(shí)現(xiàn)字典轉(zhuǎn)模型如YYModel,利用Runtime的api獲取屬性列表,賦值等操作
  • 獲取類的所有屬性/方法名稱,使用Runtime的apiclass_copyIvarList、class_copyMethodList
  • aspect切面編程
5.能否在分類中添加屬性和成員變量?能否向已存在的類添加實(shí)倒變量?
  • 分類的結(jié)構(gòu)體中沒有屬性列表,只有方法列表,原則上只能添加方法,不能添加屬性,但是可以借助運(yùn)行時(shí)關(guān)聯(lián)對(duì)象。
  • 分類中可以使用@property, 但是不會(huì)生成setter/getter方法,也不會(huì)生成私有的成員變量,編譯可以通過但引用就會(huì)報(bào)錯(cuò)。
  • 編譯后的類已經(jīng)注冊(cè)在runtime中,類結(jié)構(gòu)體中的objc_ivar_list實(shí)例變量的鏈表和instance_size實(shí)例變量的內(nèi)存大小已經(jīng)確定,同時(shí)runtime還會(huì)調(diào)用class_setIvarLayout、class_setWeakIvarLayout來處理strongweak引用,所以不能向已存在的類中添加實(shí)例變量。但是運(yùn)行時(shí)使用objc_allocateClassPair創(chuàng)建類,可以調(diào)用class_addIvar函數(shù)添加實(shí)例變量,但必須在調(diào)用objc_registerClassPair前。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iOS開發(fā)必須也是不得不了解的Runtime,今天有空能仔細(xì)的查閱下源碼同時(shí)結(jié)合許多優(yōu)秀的文章,對(duì)自己所掌握的ru...
    Mhhhhhhy閱讀 847評(píng)論 0 3
  • 一. runtime簡(jiǎn)介 runtime簡(jiǎn)稱運(yùn)行時(shí),是一套底層的 C 語言 API。OC就是運(yùn)行時(shí)機(jī)制,運(yùn)行時(shí)機(jī)制...
    沈楓_ShenF閱讀 781評(píng)論 0 2
  • C/C++ 屬于靜態(tài)的語言;而ObjC屬于動(dòng)態(tài)語言。什么是靜態(tài)語言?就是在編譯器編譯后就調(diào)用函數(shù)地址,代碼結(jié)構(gòu)就固...
    ldzSpace閱讀 547評(píng)論 0 0
  • 什么是runtime 官方描述:The Objective-C language defers as many d...
    Arthur澪閱讀 352評(píng)論 0 0
  • Runtime 運(yùn)行時(shí) 參考文章:玉令天下的博客特酷吧南峰子的技術(shù)博客顧 鵬 Objective-C是動(dòng)態(tài)語言,所...
    Karen_閱讀 786評(píng)論 1 7

友情鏈接更多精彩內(nèi)容