關(guān)于Runtime

一個(gè)objc對象如何進(jìn)行內(nèi)存布局炮姨?(考慮有父類的情況)

NSString *str = @“”;

* 所有父類的成員變量和自己的成員變量都會存放在該對象str所對應(yīng)的存儲空間中.

* 每一個(gè)對象內(nèi)部都有一個(gè)isa指針,指向他的類對象NSString,類對象中存放著本對象的

* 對象方法列表(對象能夠接收的消息列表千康,保存在它所對應(yīng)的類對象中)

* 成員變量的列表,

* 屬性列表,

* 它內(nèi)部也有一個(gè)isa指針指向元對象(meta class),(既類對象所屬的類型,用來表述NSString 是一個(gè)什么樣的對象 元對象內(nèi)部存放的是類方法列表)

* 類對象內(nèi)部還有一個(gè)superclass的指針,指向他的父類對象。

* NSObject乔妈,它的superclass指針指向nil

* 類對象既然稱為對象,那它也是一個(gè)實(shí)例。類對象中也有一個(gè)isa指針指向它的元類(meta class)欣除,即類對象是元類的實(shí)例。元類內(nèi)部存放的是類方法列表挪略,根元類的isa指針指向自己历帚,superclass指針指向NSObject類。

一個(gè)objc對象的isa的指針指向什么杠娱?有什么作用挽牢?

指向他的類對象,從而可以找到對象上的方法

objc中的類方法和實(shí)例方法有什么本質(zhì)區(qū)別和聯(lián)系?

類方法:

1. 類方法是屬于類對象的

2. 類方法只能通過類對象調(diào)用

3. 類方法中的self是類對象

4. 類方法可以調(diào)用其他的類方法

5. 類方法中不能訪問成員變量

6. 類方法中不能直接調(diào)用對象方法

實(shí)例方法:

1. 實(shí)例方法是屬于實(shí)例對象的

2. 實(shí)例方法只能通過實(shí)例對象調(diào)用

3. 實(shí)例方法中的self是實(shí)例對象

4. 實(shí)例方法中可以訪問成員變量

5. 實(shí)例方法中直接調(diào)用實(shí)例方法

6. 實(shí)例方法中也可以調(diào)用類方法(通過類名)

runtime如何通過selector找到對應(yīng)的IMP地址摊求?(分別考慮類方法和實(shí)例方法)禽拔?

每一個(gè)類對象中都一個(gè)方法列表,方法列表中記錄著方法的名稱,方法實(shí)現(xiàn),以及參數(shù)類型,其實(shí)selector本質(zhì)就是方法名稱,通過這個(gè)方法名稱就可以在方法列表中找到對應(yīng)的方法實(shí)現(xiàn).

objc中向一個(gè)nil對象發(fā)送消息將會發(fā)生什么?

objc在向一個(gè)對象發(fā)送消息時(shí)室叉,runtime庫會根據(jù)對象的isa指針找到該對象實(shí)際所屬的類睹栖,然后在該類中的方法列表以及其父類方法列表中尋找方法運(yùn)行,如果向一個(gè)nil對象發(fā)送消息茧痕,首先在尋找對象的isa指針時(shí)就是0地址返回了野来,所以不會出現(xiàn)任何錯誤。

objc中向一個(gè)對象發(fā)送消息[obj foo]和objc_msgSend()函數(shù)之間有什么關(guān)系踪旷?

objc是動態(tài)語言曼氛,每個(gè)方法在運(yùn)行時(shí)會被動態(tài)轉(zhuǎn)為消息發(fā)送豁辉,即:objc_msgSend(receiver, selector)。

[obj foo];在objc動態(tài)編譯時(shí)舀患,會被轉(zhuǎn)意為:objc_msgSend(obj, @selector(foo));徽级。

什么時(shí)候會報(bào)unrecognized selector的異常?

objc在向一個(gè)對象發(fā)送消息時(shí)聊浅,runtime庫會根據(jù)對象的isa指針找到該對象實(shí)際所屬的類餐抢,然后在該類中的方法列表以及其父類方法列表中尋找方法運(yùn)行,如果狗超,在最頂層的父類中依然找不到相應(yīng)的方法時(shí)弹澎,程序在運(yùn)行時(shí)會掛掉并拋出異常unrecognized selector sent to XXX 。但是在這之前努咐,objc的運(yùn)行時(shí)會給出三次拯救程序崩潰的機(jī)會:

1. Method resolutionobjc運(yùn)行時(shí)會調(diào)用+resolveInstanceMethod:或者 +resolveClassMethod:苦蒿,讓你有機(jī)會提供一個(gè)函數(shù)實(shí)現(xiàn)。如果你添加了函數(shù)渗稍,那運(yùn)行時(shí)系統(tǒng)就會重新啟動一次消息發(fā)送的過程佩迟,否則 ,運(yùn)行時(shí)就會移到下一步竿屹,消息轉(zhuǎn)發(fā)(Message Forwarding)报强。

2. Fast forwarding如果目標(biāo)對象實(shí)現(xiàn)了-forwardingTargetForSelector:,Runtime 這時(shí)就會調(diào)用這個(gè)方法拱燃,給你把這個(gè)消息轉(zhuǎn)發(fā)給其他對象的機(jī)會秉溉。既能不能把這條消息轉(zhuǎn)發(fā)給其他接受者處理, 只要這個(gè)方法返回的不是nil和self碗誉,整個(gè)消息發(fā)送的過程就會被重啟召嘶,當(dāng)然發(fā)送的對象會變成你返回的那個(gè)對象。否則哮缺,就會繼續(xù)Normal Fowarding弄跌。 這里叫Fast,只是為了區(qū)別下一步的轉(zhuǎn)發(fā)機(jī)制尝苇。因?yàn)檫@一步不會創(chuàng)建任何新的對象铛只,但下一步轉(zhuǎn)發(fā)會創(chuàng)建一個(gè)NSInvocation對象,所以相對更快點(diǎn)糠溜。

3. Normal forwarding這一步是Runtime最后一次給你挽救的機(jī)會淳玩。首先它會發(fā)送-methodSignatureForSelector:消息獲得函數(shù)的參數(shù)和返回值類型。如果-methodSignatureForSelector:返回nil非竿,Runtime則會發(fā)出-doesNotRecognizeSelector:消息凯肋,程序這時(shí)也就掛掉了。如果返回了一個(gè)函數(shù)簽名汽馋,Runtime就會創(chuàng)建一個(gè)NSInvocation對象并發(fā)送-forwardInvocation:消息給目標(biāo)對象侮东。

下面的代碼輸出什么?

@implementation Son : Father

- (id)init

{

self = [super init];

if (self) {

NSLog(@"%@", NSStringFromClass([self class]));

NSLog(@"%@", NSStringFromClass([super class]));

}

return self;

}

@end

其實(shí) super 是一個(gè) Magic Keyword豹芯, 它本質(zhì)是一個(gè)編譯器標(biāo)示符悄雅,和 self 是指向的同一個(gè)消息接受者!他們兩個(gè)的不同點(diǎn)在于:super 會告訴編譯器铁蹈,調(diào)用 class 這個(gè)方法時(shí)宽闲,要去父類的方法,而不是本類里的握牧。

上面的例子不管調(diào)用[self class]還是[super class]容诬,接受消息的對象都是當(dāng)前 Son *xxx 這個(gè)對象。

當(dāng)使用 self 調(diào)用方法時(shí)沿腰,會從當(dāng)前類的方法列表中開始找览徒,如果沒有,就從父類中再找颂龙;而當(dāng)使用 super 時(shí)习蓬,則從父類的方法列表中開始找。然后調(diào)用父類的這個(gè)方法措嵌。

_objc_msgForward函數(shù)是做什么的躲叼,直接調(diào)用它將會發(fā)生什么?

_objc_msgForward是 IMP 類型企巢,用于消息轉(zhuǎn)發(fā)的:當(dāng)向一個(gè)對象發(fā)送一條消息枫慷,但它并沒有實(shí)現(xiàn)的時(shí)候,_objc_msgForward會嘗試做消息轉(zhuǎn)發(fā)浪规。

結(jié)合《NSObject官方文檔》或听,排除掉 NSObject 做的事,剩下的就是_objc_msgForward消息轉(zhuǎn)發(fā)做的幾件事:

1. 調(diào)用resolveInstanceMethod:方法 (或 resolveClassMethod:)罗丰。允許用戶在此時(shí)為該 Class 動態(tài)添加實(shí)現(xiàn)神帅。如果有實(shí)現(xiàn)了,則調(diào)用并返回YES萌抵,那么重新開始o(jì)bjc_msgSend流程找御。這一次對象會響應(yīng)這個(gè)選擇器,一般是因?yàn)樗呀?jīng)調(diào)用過class_addMethod绍填。如果仍沒實(shí)現(xiàn)霎桅,繼續(xù)下面的動作。

2. 調(diào)用forwardingTargetForSelector:方法讨永,嘗試找到一個(gè)能響應(yīng)該消息的對象滔驶。如果獲取到,則直接把消息轉(zhuǎn)發(fā)給它卿闹,返回非 nil 對象揭糕。否則返回 nil 萝快,繼續(xù)下面的動作。注意著角,這里不要返回 self 揪漩,否則會形成死循環(huán)。

3. 調(diào)用methodSignatureForSelector:方法吏口,嘗試獲得一個(gè)方法簽名奄容。如果獲取不到,則直接調(diào)用doesNotRecognizeSelector拋出異常产徊。如果能獲取昂勒,則返回非nil:創(chuàng)建一個(gè) NSlnvocation 并傳給forwardInvocation:。

4. 調(diào)用forwardInvocation:方法舟铜,將第3步獲取到的方法簽名包裝成 Invocation 傳入戈盈,如何處理就在這里面了,并返回非ni深滚。

5. 調(diào)用doesNotRecognizeSelector: 奕谭,默認(rèn)的實(shí)現(xiàn)是拋出異常。如果第3步?jīng)]能獲得一個(gè)方法簽名痴荐,執(zhí)行該步驟血柳。

一旦調(diào)用_objc_msgForward,將跳過查找 IMP 的過程生兆,直接觸發(fā)“消息轉(zhuǎn)發(fā)”难捌,

如果調(diào)用了_objc_msgForward,即使這個(gè)對象確實(shí)已經(jīng)實(shí)現(xiàn)了這個(gè)方法鸦难,你也會告訴objc_msgSend:“我沒有在這個(gè)對象里找到這個(gè)方法的實(shí)現(xiàn)”

有哪些場景需要直接調(diào)用_objc_msgForward根吁?最常見的場景是:你想獲取某方法所對應(yīng)的NSInvocation對象。舉例說明:

JSPatch (Github 鏈接)就是直接調(diào)用_objc_msgForward來實(shí)現(xiàn)其核心功能的:

JSPatch 以小巧的體積做到了讓JS調(diào)用/替換任意OC方法合蔽,讓iOS APP具備熱更新的能力击敌。

能否向編譯后得到的類中增加實(shí)例變量?能否向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量拴事?為什么沃斤?

* 不能向編譯后得到的類中增加實(shí)例變量;

* 能向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量刃宵;

解釋下:

* 因?yàn)榫幾g后的類已經(jīng)注冊在 runtime 中衡瓶,類結(jié)構(gòu)體中的 objc_ivar_list 實(shí)例變量的鏈表 和 instance_size 實(shí)例變量的內(nèi)存大小已經(jīng)確定,同時(shí)runtime 會調(diào)用 class_setIvarLayout 或 class_setWeakIvarLayout 來處理 strong weak 引用牲证。所以不能向存在的類中添加實(shí)例變量哮针;

* 運(yùn)行時(shí)創(chuàng)建的類是可以添加實(shí)例變量,調(diào)用 class_addIvar 函數(shù)。但是得在調(diào)用 objc_allocateClassPair 之后十厢,objc_registerClassPair 之前等太,原因同上。

http://www.reibang.com/p/e071206103a4 runtime 的使用場景

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寿烟,一起剝皮案震驚了整個(gè)濱河市澈驼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌筛武,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挎塌,死亡現(xiàn)場離奇詭異徘六,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)榴都,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門待锈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嘴高,你說我怎么就攤上這事竿音。” “怎么了拴驮?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵春瞬,是天一觀的道長。 經(jīng)常有香客問我套啤,道長宽气,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任潜沦,我火速辦了婚禮萄涯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘唆鸡。我一直安慰自己涝影,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布争占。 她就那樣靜靜地躺著燃逻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪燃乍。 梳的紋絲不亂的頭發(fā)上唆樊,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音刻蟹,去河邊找鬼逗旁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的片效。 我是一名探鬼主播红伦,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼淀衣!你這毒婦竟也來了昙读?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤膨桥,失蹤者是張志新(化名)和其女友劉穎蛮浑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體只嚣,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沮稚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了册舞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蕴掏。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖调鲸,靈堂內(nèi)的尸體忽然破棺而出盛杰,到底是詐尸還是另有隱情,我是刑警寧澤藐石,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布即供,位于F島的核電站,受9級特大地震影響贯钩,放射性物質(zhì)發(fā)生泄漏募狂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一角雷、第九天 我趴在偏房一處隱蔽的房頂上張望祸穷。 院中可真熱鬧,春花似錦勺三、人聲如沸雷滚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祈远。三九已至,卻和暖如春商源,著一層夾襖步出監(jiān)牢的瞬間车份,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工牡彻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扫沼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像缎除,于是被迫代替她去往敵國和親严就。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉器罐,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,719評論 0 9
  • 1.理解NSObject和元類 1.1 在OC中的對象和類是什么 對象是在objc.h中定義的 類是在runtim...
    HWenj閱讀 924評論 0 3
  • 原文出處:南峰子的技術(shù)博客 Objective-C語言是一門動態(tài)語言梢为,它將很多靜態(tài)語言在編譯和鏈接時(shí)期做的事放到了...
    _燴面_閱讀 1,231評論 1 5
  • 文中的實(shí)驗(yàn)代碼我放在了這個(gè)項(xiàng)目中。 以下內(nèi)容是我通過整理[這篇博客] (http://yulingtianxia....
    茗涙閱讀 923評論 0 6
  • 本文詳細(xì)整理了 Cocoa 的 Runtime 系統(tǒng)的知識轰坊,它使得 Objective-C 如虎添翼铸董,具備了靈活的...
    lylaut閱讀 800評論 0 4