iOS 底層面試

1、Runtime是什么?

Runtime是一套API,有C C++ 匯編寫成,為OC語言加入了面向?qū)ο蠛瓦\(yùn)行時(shí)功能。
運(yùn)行時(shí)(Runtime)是指將數(shù)據(jù)類型的確定由編譯時(shí)推遲到了運(yùn)行時(shí)。(例如extension-category的區(qū)別)。
平時(shí)寫的OC代碼,在運(yùn)行時(shí)會(huì)被轉(zhuǎn)換成Runtime的C語言代碼,Runtime是OC的幕后工作者。

2、方法的本質(zhì)?SEL是什么?IMP是什么?兩者之間的關(guān)系又是什么?

方法的本質(zhì)是發(fā)送消息,發(fā)送消息會(huì)有以下幾個(gè)流程。

  • 快速查找:(objc_msgSend)~cache_t 緩存消息。
  • 慢速查找:遞歸自己和父類~lookUpImpOrForward。
  • 查找不到消息:動(dòng)態(tài)方法解析~resolveInstanceMethod
  • 消息快速轉(zhuǎn)發(fā):forwardingTargetForSelector。
  • 慢速消息轉(zhuǎn)發(fā):methodSignatureForSelector&forwardInvocation。
  • 拋出異常:doesNotRecognizeSelector

SEL是方法編號(hào),在read_images時(shí)期就已經(jīng)編譯進(jìn)內(nèi)存。IMP是我們的函數(shù)實(shí)現(xiàn)指針。找IMP就是找函數(shù)的過程。
SEL就相當(dāng)于是我們書本目錄的標(biāo)題。
IMP就相當(dāng)于是我們書本目錄標(biāo)題對(duì)應(yīng)的頁碼。

3、能否向編譯后的得到的類中增加實(shí)例變量?能否向運(yùn)行時(shí)創(chuàng)建的類中增加實(shí)例變量?

  • 不能向編譯后的類中增加實(shí)例變量,因?yàn)橐坏┚幾g完成,類中的內(nèi)存結(jié)構(gòu)就已經(jīng)確定,編譯后的實(shí)例變量存儲(chǔ)的ro中,我們無法修改。
  • 只要還沒有注冊(cè)到內(nèi)存中,就可以添加。
  • 可以在運(yùn)行時(shí)添加屬性和方法。

4、self&super

@implementation LGPerson
- (instancetype)init
{
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}
@end

我們通過clang將這段代碼轉(zhuǎn)換成C++。

static instancetype _I_LGPerson_init(LGPerson * self, SEL _cmd) {
    self = ((LGPerson *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("LGPerson"))}, sel_registerName("init"));
    if (self) {
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_dq_m1fkwntx6rsbzm4157sqxsnc0000gn_T_LGPerson_8ad7e9_mi_0, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"))));
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_dq_m1fkwntx6rsbzm4157sqxsnc0000gn_T_LGPerson_8ad7e9_mi_1, NSStringFromClass(((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("LGPerson"))}, sel_registerName("class"))));
    }
    return self;
}

精簡代碼后

NSStringFromClass(objc_msgSend((id)self, sel_registerName("class")));
NSStringFromClass(objc_msgSendSuper({(id)self, (id)class_getSuperclass(objc_getClass("LGPerson"))}, sel_registerName("class"))));

我們發(fā)現(xiàn)super關(guān)鍵字底層調(diào)用的是objc_msgSendSuper

 * id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
 *
 * struct objc_super {
 *     id receiver;
 *     Class cls;   // the class to search
 * }

我們發(fā)現(xiàn)objc_super結(jié)構(gòu)體的第一個(gè)成員變量receiver也就是我們的消息接受者。對(duì)比上面轉(zhuǎn)換后的代碼我們可以發(fā)現(xiàn)receiver的值傳入的是self,也就是說我們當(dāng)前的消息接受者就是我們當(dāng)前的對(duì)象,只不過它是從父類的消息列表中開始查找函數(shù)的實(shí)現(xiàn)。最后交由self去處理。
所以上面的兩次輸出都是LGPerson

?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 一、OC語法 1、OC對(duì)象的本質(zhì) 1)一個(gè)NSObject對(duì)象占用多少內(nèi)存?A:系統(tǒng)分配16個(gè)字節(jié)給一個(gè)NSObj...
    wanglei1702閱讀 707評(píng)論 0 1
  • 簡介 Runtime 又叫運(yùn)行時(shí),是一套底層的 C 語言 API,其為 iOS 內(nèi)部的核心之一,我們平時(shí)編寫的 O...
    專業(yè)男神經(jīng)閱讀 960評(píng)論 0 2
  • 本文轉(zhuǎn)載自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex閱讀 883評(píng)論 0 1
  • 面向?qū)ο蟮娜筇匦裕悍庋b、繼承、多態(tài) OC內(nèi)存管理 _strong 引用計(jì)數(shù)器來控制對(duì)象的生命周期。 _weak...
    運(yùn)氣不夠技術(shù)湊閱讀 1,222評(píng)論 0 10
  • 我們常常會(huì)聽說 Objective-C 是一門動(dòng)態(tài)語言,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,327評(píng)論 0 7

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