1.Category 的實(shí)現(xiàn)原理?
Category 實(shí)際上是 Category_t的結(jié)構(gòu)體,在運(yùn)行時(shí),新添加的方法,都被以倒序插入到原有方法列表的最前面,所以不同的Category,添加了同一個(gè)方法,執(zhí)行的實(shí)際上是最后一個(gè)。
Category 在剛剛編譯完的時(shí)候,和原來的類是分開的,只有在程序運(yùn)行起來后,通過 Runtime ,Category 和原來的類才會(huì)合并到一起。
2.isa指針的理解,對(duì)象的isa指針指向哪里?isa指針有哪兩種類型?
-
isa 等價(jià)于 is kind of
實(shí)例對(duì)象的 isa 指向類對(duì)象
類對(duì)象的 isa 指向元類對(duì)象
元類對(duì)象的 isa 指向元類的基類
-
isa 有兩種類型
純指針,指向內(nèi)存地址
NON_POINTER_ISA,除了內(nèi)存地址,還存有一些其他信息
3.Objective-C 如何實(shí)現(xiàn)多重繼承?
Object-c的類沒有多繼承,只支持單繼承,如果要實(shí)現(xiàn)多繼承的話,可使用如下幾種方式間接實(shí)現(xiàn)
-
通過組合實(shí)現(xiàn)
A和B組合,作為C類的組件
-
通過協(xié)議實(shí)現(xiàn)
C類實(shí)現(xiàn)A和B類的協(xié)議方法
-
消息轉(zhuǎn)發(fā)實(shí)現(xiàn)
forwardInvocation:方法
4.runtime 如何實(shí)現(xiàn) weak 屬性?
weak 此特質(zhì)表明該屬性定義了一種「非擁有關(guān)系」(nonowning relationship)。為這種屬性設(shè)置新值時(shí),設(shè)置方法既不持有新值(新指向的對(duì)象),也不釋放舊值(原來指向的對(duì)象)。
runtime 對(duì)注冊(cè)的類,會(huì)進(jìn)行內(nèi)存布局,從一個(gè)粗粒度的概念上來講,這時(shí)候會(huì)有一個(gè) hash 表,這是一個(gè)全局表,表中是用 weak 指向的對(duì)象內(nèi)存地址作為 key,用所有指向該對(duì)象的 weak 指針表作為 value。當(dāng)此對(duì)象的引用計(jì)數(shù)為 0 的時(shí)候會(huì) dealloc,假如該對(duì)象內(nèi)存地址是 a,那么就會(huì)以 a 為 key,在這個(gè) weak 表中搜索,找到所有以 a 為鍵的 weak 對(duì)象,從而設(shè)置為 nil。
runtime 如何實(shí)現(xiàn) weak 屬性具體流程大致分為 3 步:
1、初始化時(shí):runtime 會(huì)調(diào)用 objc_initWeak 函數(shù),初始化一個(gè)新的 weak 指針指向?qū)ο蟮牡刂贰?/p>
2、添加引用時(shí):objc_initWeak 函數(shù)會(huì)調(diào)用 objc_storeWeak() 函數(shù),objc_storeWeak() 的作用是更新指針指向(指針可能原來指向著其他對(duì)象,這時(shí)候需要將該 weak 指針與舊對(duì)象解除綁定,會(huì)調(diào)用到 weak_unregister_no_lock),如果指針指向的新對(duì)象非空,則創(chuàng)建對(duì)應(yīng)的弱引用表,將 weak 指針與新對(duì)象進(jìn)行綁定,會(huì)調(diào)用到 weak_register_no_lock。在這個(gè)過程中,為了防止多線程中競(jìng)爭(zhēng)沖突,會(huì)有一些鎖的操作。
3、釋放時(shí):調(diào)用 clearDeallocating 函數(shù),clearDeallocating 函數(shù)首先根據(jù)對(duì)象地址獲取所有 weak 指針地址的數(shù)組,然后遍歷這個(gè)數(shù)組把其中的數(shù)據(jù)設(shè)為 nil,最后把這個(gè) entry 從 weak 表中刪除,最后清理對(duì)象的記錄。
5.講一下 OC 的消息機(jī)制
OC中的方法調(diào)用其實(shí)都是轉(zhuǎn)成了objc_msgSend函數(shù)的調(diào)用,給receiver(方法調(diào)用者)發(fā)送了一條消息(selector方法名)
objc_msgSend底層有3大階段,消息發(fā)送(當(dāng)前類、父類中查找)、動(dòng)態(tài)方法解析、消息轉(zhuǎn)發(fā)
6.runtime具體應(yīng)用
利用關(guān)聯(lián)對(duì)象(AssociatedObject)給分類添加屬性
遍歷類的所有成員變量(修改textfield的占位文字顏色、字典轉(zhuǎn)模型、自動(dòng)歸檔解檔)
交換方法實(shí)現(xiàn)(交換系統(tǒng)的方法)
利用消息轉(zhuǎn)發(fā)機(jī)制解決方法找不到的異常問題
KVC 字典轉(zhuǎn)模型
7.runtime如何通過selector找到對(duì)應(yīng)的IMP地址?
每一個(gè)類對(duì)象中都一個(gè)對(duì)象方法列表(對(duì)象方法緩存)
類方法列表是存放在類對(duì)象中isa指針指向的元類對(duì)象中(類方法緩存)。
方法列表中每個(gè)方法結(jié)構(gòu)體中記錄著方法的名稱,方法實(shí)現(xiàn),以及參數(shù)類型,其實(shí)selector本質(zhì)就是方法名稱,通過這個(gè)方法名稱就可以在方法列表中找到對(duì)應(yīng)的方法實(shí)現(xiàn)。
當(dāng)我們發(fā)送一個(gè)消息給一個(gè)NSObject對(duì)象時(shí),這條消息會(huì)在對(duì)象的類對(duì)象方法列表里查找。
當(dāng)我們發(fā)送一個(gè)消息給一個(gè)類時(shí),這條消息會(huì)在類的Meta Class對(duì)象的方法列表里查找。
8.簡(jiǎn)述下Objective-C中調(diào)用方法的過程
Objective-C是動(dòng)態(tài)語言,每個(gè)方法在運(yùn)行時(shí)會(huì)被動(dòng)態(tài)轉(zhuǎn)為消息發(fā)送,即:objc_msgSend(receiver, selector),整個(gè)過程介紹如下:
objc在向一個(gè)對(duì)象發(fā)送消息時(shí),runtime庫會(huì)根據(jù)對(duì)象的isa指針找到該對(duì)象實(shí)際所屬的類
然后在該類中的方法列表以及其父類方法列表中尋找方法運(yùn)行
如果,在最頂層的父類(一般也就NSObject)中依然找不到相應(yīng)的方法時(shí),程序在運(yùn)行時(shí)會(huì)掛掉并拋出異常unrecognized selector sent to XXX
但是在這之前,objc的運(yùn)行時(shí)會(huì)給出三次拯救程序崩潰的機(jī)會(huì),這三次拯救程序奔潰的說明見問題《什么時(shí)候會(huì)報(bào)unrecognized selector的異?!分械恼f明。
9.load和initialize的區(qū)別
兩者都會(huì)自動(dòng)調(diào)用父類的,不需要super操作,且僅會(huì)調(diào)用一次(不包括外部顯示調(diào)用).
load和initialize方法都會(huì)在實(shí)例化對(duì)象之前調(diào)用,以main函數(shù)為分水嶺,前者在main函數(shù)之前調(diào)用,后者在之后調(diào)用。這兩個(gè)方法會(huì)被自動(dòng)調(diào)用,不能手動(dòng)調(diào)用它們。
load和initialize方法都不用顯示的調(diào)用父類的方法而是自動(dòng)調(diào)用,即使子類沒有initialize方法也會(huì)調(diào)用父類的方法,而load方法則不會(huì)調(diào)用父類。
load方法通常用來進(jìn)行Method Swizzle,initialize方法一般用于初始化全局變量或靜態(tài)變量。
load和initialize方法內(nèi)部使用了鎖,因此它們是線程安全的。實(shí)現(xiàn)時(shí)要盡可能保持簡(jiǎn)單,避免阻塞線程,不要再使用鎖。
10.怎么理解Objective-C是動(dòng)態(tài)運(yùn)行時(shí)語言。
主要是將數(shù)據(jù)類型的確定由編譯時(shí),推遲到了運(yùn)行時(shí)。這個(gè)問題其實(shí)淺涉及到兩個(gè)概念,運(yùn)行時(shí)和多態(tài)。
簡(jiǎn)單來說, 運(yùn)行時(shí)機(jī)制使我們直到運(yùn)行時(shí)才去決定一個(gè)對(duì)象的類別,以及調(diào)用該類別對(duì)象指定方法。
多態(tài):不同對(duì)象以自己的方式響應(yīng)相同的消息的能力叫做多態(tài)。
意思就是假設(shè)生物類(life)都擁有一個(gè)相同的方法-eat;那人類屬于生物,豬也屬于生物,都繼承了life后,實(shí)現(xiàn)各自的eat,但是調(diào)用是我們只需調(diào)用各自的eat方法。也就是不同的對(duì)象以自己的方式響應(yīng)了相同的消 息(響應(yīng)了eat這個(gè)選擇器)。因此也可以說,運(yùn)行時(shí)機(jī)制是多態(tài)的基礎(chǔ).
需要更多iOS學(xué)習(xí)資料、BAT大廠面試真題,可加 iOS技術(shù)探討群:937194184,群文件直接獲取
如下圖所示:
