1.你使用過Objective-C的運(yùn)行時(shí)編程么痴柔?如果使用過,你用它做了什么疫向?你還能記得你所使用的相關(guān)的頭文件或者某些方法的名稱嗎咳蔚?
NSObjCRuntime.h/NSObject.h/message.h/objc-api.h/objc-auto.h/objc-exception.h(異常操作)/objc-sync.h/objc.h(基本功能)/runtime.h(主要功能在runtime.h中)
2.runtime實(shí)現(xiàn)的機(jī)制是什么,怎么用,一般用于干嘛搔驼?
runtime是一套比較底層的純C語(yǔ)言API, 屬于1個(gè)C語(yǔ)言庫(kù), 包含了很多底層的C語(yǔ)言API谈火。平時(shí)編寫的OC代碼, 在程序運(yùn)行過程中, 其實(shí)最終都是轉(zhuǎn)成了runtime的C語(yǔ)言代碼, runtime算是OC的幕后工作者。
runtime是屬于OC的底層, 可以進(jìn)行一些非常底層的操作(用OC是無(wú)法現(xiàn)實(shí)的, 不好實(shí)現(xiàn))
- 在程序運(yùn)行過程中, 動(dòng)態(tài)創(chuàng)建一個(gè)類(比如KVO的底層實(shí)現(xiàn))
- 在程序運(yùn)行過程中, 動(dòng)態(tài)地為某個(gè)類添加屬性方法, 修改屬性值
遍歷一個(gè)類的所有成員變量(屬性)所有方法
3.kvo的實(shí)現(xiàn)原理是什么?
KVO是基于runtime機(jī)制實(shí)現(xiàn)的舌涨。
當(dāng)某個(gè)類的對(duì)象第一次被觀察時(shí)糯耍,系統(tǒng)就會(huì)在運(yùn)行期動(dòng)態(tài)地創(chuàng)建該類的一個(gè)派生類,在這個(gè)派生類中重寫基類中任何被觀察屬性的setter方法囊嘉。
派生類在被重寫的setter方法實(shí)現(xiàn)真正的通知機(jī)制(Person->NSKVONOtifying Person)
Person類對(duì)象p設(shè)置self控制器且設(shè)置監(jiān)聽屬性温技,就會(huì)調(diào)用observeValueForKeyPath方法,當(dāng)Person類的屬性被改變時(shí),就會(huì)動(dòng)態(tài)生成一個(gè)子類繼承自Person類(NSKVONotifying_Person),重寫setAge方法扬舒,內(nèi)部調(diào)用父類setAge方法正罢,通知監(jiān)聽器
[監(jiān)聽器 observeValueForKeyPath:@"age" ofObject:self change:@{} context:(void *)context];
原先age屬性不改變時(shí)p對(duì)象 isa指向Person,當(dāng)age屬性改變時(shí)p對(duì)象 isa指向NSKVONotifying_Person(setAge重新內(nèi)部就會(huì)傳遞變量至父類且通知監(jiān)聽器age屬性改變)
4.objc_setAssociatedObject哲嘲、objc_getAssociatedObject是什么,有什么優(yōu)點(diǎn)?
建立對(duì)象關(guān)聯(lián),使用關(guān)聯(lián),我們可以不用修改類的定義而為其對(duì)象增加存儲(chǔ)空間俩滥。這在我們無(wú)法訪問到類的源碼的時(shí)候或者是考慮到二進(jìn)制兼容性的時(shí)候是非常有用。
關(guān)聯(lián)是基于關(guān)鍵字的贺奠,因此霜旧,我們可以為任何對(duì)象增加任意多的關(guān)聯(lián),每個(gè)都使用不同的關(guān)鍵字即可儡率。關(guān)聯(lián)是可以保證被關(guān)聯(lián)的對(duì)象在關(guān)聯(lián)對(duì)象的整個(gè)生命周期都是可用的(在垃圾自動(dòng)回收環(huán)境下也不會(huì)導(dǎo)致資源不可回收)挂据。
5.method swizzling是干什么的,一般用于哪里?
方法混用,可以通過runtime獲取類的方法表儿普。一個(gè)方法Method由三個(gè)部分組成SEL方法選標(biāo)崎逃、IMP函數(shù)指針、typeEncode眉孩「錾埽可以直接class_replaceMethod替換原有方法勒葱,method_exchangeImplementations效果兩個(gè)方法的實(shí)現(xiàn)或者method_setImplementation直接修改方法實(shí)現(xiàn)。
向視圖控制器的生命周期中注入操作巴柿、事件的響應(yīng)凛虽、視圖的繪制,或Foundation中的網(wǎng)絡(luò)堆棧都是能夠利用method swizzling產(chǎn)生明顯效果的場(chǎng)景广恢。還有一些其他的場(chǎng)景使用swizzling會(huì)是一個(gè)合適的選擇凯旋,這隨著Objective-C開發(fā)者經(jīng)驗(yàn)不斷豐富會(huì)變得越來越明顯。
6.可以向nil對(duì)象發(fā)送消息么?如果向一個(gè)nil對(duì)象發(fā)送消息將會(huì)發(fā)生什么?
在Objective-C中向nil發(fā)送消息是完全有效的——只是在運(yùn)行時(shí)不會(huì)有任何作用袁波。
7.category瓦阐,method 的實(shí)現(xiàn)機(jī)制是什么?
根據(jù)蘋果官方文檔對(duì) Category 的描述,它的使用場(chǎng)景主要有三個(gè):
給現(xiàn)有的類添加方法篷牌;
將一個(gè)類的實(shí)現(xiàn)拆分成多個(gè)獨(dú)立的源文件睡蟋;無(wú)論我們有沒有主動(dòng)引入 Category 的頭文件,Category 中的方法都會(huì)被添加進(jìn)主類中枷颊。將 Category 和它的主類(或元類)注冊(cè)到哈希表中戳杀;
如果主類(或元類)已實(shí)現(xiàn),那么重建它的方法列表夭苗。
在這里分了兩種情況進(jìn)行處理:Category 中的實(shí)例方法和屬性被整合到主類中信卡;而類方法則被整合到元類中。將 Category 中的方法题造、屬性和協(xié)議整合到類(主類或元類)中傍菇,更新類的數(shù)據(jù)字段 data() 中 method_lists(或 method_list) 、 properties 和 protocols 的值界赔。
8.runtime如何實(shí)現(xiàn)weak變量的自動(dòng)置nil丢习?
runtime 對(duì)注冊(cè)的類, 會(huì)進(jìn)行布局淮悼,對(duì)于 weak 對(duì)象會(huì)放入一個(gè) hash 表中咐低。 用 weak 指向的對(duì)象內(nèi)存地址作為 key,當(dāng)此對(duì)象的引用計(jì)數(shù)為0的時(shí)候會(huì) dealloc袜腥,假如 weak 指向的對(duì)象內(nèi)存地址是a见擦,那么就會(huì)以a為鍵, 在這個(gè) weak 表中搜索羹令,找到所有以a為鍵的 weak 對(duì)象鲤屡,從而設(shè)置為 nil。
9.objc使用什么機(jī)制管理對(duì)象內(nèi)存福侈?
通過 retainCount 的機(jī)制來決定對(duì)象是否需要釋放酒来。 每次 runloop 的時(shí)候,都會(huì)檢查對(duì)象的 retainCount癌刽,如果retainCount 為 0役首,說明該對(duì)象沒有地方需要繼續(xù)使用了,可以釋放掉了显拜。
10.為什么說Object-C是runtime language? runtime有什么優(yōu)點(diǎn)?
將數(shù)據(jù)類型的確定由編譯時(shí)衡奥,推遲到了運(yùn)行時(shí)。運(yùn)行時(shí)機(jī)制使我們直到運(yùn)行時(shí)才去決定一個(gè)對(duì)象的類別远荠,以及調(diào)用該類別對(duì)象指定方法矮固。實(shí)現(xiàn)多態(tài),不同對(duì)象以自己的方式響應(yīng)相同的消息的能力譬淳。
11.什么是動(dòng)態(tài)档址,舉例說明
OC具有很多的動(dòng)態(tài)特性,有動(dòng)態(tài)類型(Dynamic typing),動(dòng)態(tài)綁定(Dynamic binding)和動(dòng)態(tài)加載(Dynamic loading).OC在底層也提供了相當(dāng)豐富的運(yùn)行時(shí)特性,比如枚舉類屬性方法,獲取方法實(shí)現(xiàn)等.
動(dòng)態(tài)特性 :
動(dòng)態(tài)類型:即運(yùn)行時(shí)再?zèng)Q定對(duì)象的類型.id類型即通用的對(duì)象類,任何的對(duì)象都可以用id類型來指向(通常用于不知道該對(duì)象為什么類型的對(duì)象的時(shí)候才使用).
id obj = name;
if ([obj isKindOfClass:[NSString class]]) {
NSString * str = (NSString *)name;
}
isKindOfClass:用于確定某個(gè)NSObject對(duì)象是否是某個(gè)類的成員. 而isMemberOfClass:是NSObject方法,用于確定某個(gè)對(duì)象是否是某個(gè)類或其子類的成員
動(dòng)態(tài)綁定:經(jīng)過動(dòng)態(tài)類型確定實(shí)例對(duì)象之后,該實(shí)例對(duì)象對(duì)應(yīng)的屬性和一些方法也隨即被確定,根據(jù)類的確定,確定了類的屬性和類的方法.OC中調(diào)用一個(gè)實(shí)例的方法,就是通過OC的消息機(jī)制發(fā)送一個(gè)消息,實(shí)例在收到消息后,從自身的實(shí)現(xiàn)中找到方法來響應(yīng).動(dòng)態(tài)綁定就是實(shí)例所屬的類經(jīng)過運(yùn)行后確定,將類的屬性和方法綁定在動(dòng)態(tài)類型上,而不是實(shí)現(xiàn)確定的,因?yàn)轭愐彩莿?dòng)態(tài)類型的
動(dòng)態(tài)加載:所謂動(dòng)態(tài)加載就是我們做開發(fā)的時(shí)候icon圖片的時(shí)候在Retina設(shè)備上要多添加一個(gè)張@2x的圖片,當(dāng)設(shè)備更換的時(shí)候,圖片也會(huì)自動(dòng)的替換,還有就是我們公司主板項(xiàng)目中根據(jù)服務(wù)器返回的類名來動(dòng)態(tài)創(chuàng)建類.
iOS開發(fā)的運(yùn)行時(shí)特性
我們做開發(fā)的時(shí)候會(huì)經(jīng)常用到Protocol-Delegate的設(shè)計(jì)模式,所以不管是我們使用的,還是我們自己定義的delegate指針類型必須是id類型的,只有這樣我們才能夠滿足程序運(yùn)行時(shí)delegate的來回切換.
12.runtime有啥用?
1>能動(dòng)態(tài)產(chǎn)生一個(gè)類、一個(gè)成員變量邻梆、一個(gè)方法
2>能動(dòng)態(tài)修改一個(gè)類守伸、一個(gè)成員變量、一個(gè)方法
3>能動(dòng)態(tài)刪除一個(gè)類浦妄、一個(gè)成員變量尼摹、一個(gè)方法
其常見的函數(shù)、頭文件
import <objc/runtime.h> : 成員變量剂娄、類蠢涝、方法
class_copyIvarList : 獲得某個(gè)類內(nèi)部的所有成員變量
class_copyMethodList : 獲得某個(gè)類內(nèi)部的所有方法
class_getInstanceMethod : 獲得某個(gè)具體的實(shí)例方法(對(duì)象方法,減號(hào)開頭)
class_getClassMethod : 獲得某個(gè)具體的類方法 (加號(hào))
method_exchangeImplementations : 交換2個(gè)方法的實(shí)現(xiàn)
import <objc/message.h> 消息機(jī)制
objc_msgSend(...);
runtime可以實(shí)現(xiàn)遍歷所有成員變量阅懦,使用runtime機(jī)制和二,某類交換2個(gè)方法的實(shí)現(xiàn)交換2個(gè)方法的好處:以后一個(gè)大項(xiàng)目當(dāng)中的一個(gè)方法使用過多,想動(dòng)一些手腳和操作耳胎,就可以很方便實(shí)現(xiàn)惯吕。