iOS 底層知識(shí)總結(jié)

一驯用、OC語法

1没咙、OC對象的本質(zhì)

1)一個(gè)NSObject對象占用多少內(nèi)存立膛?
A:系統(tǒng)分配16個(gè)字節(jié)給一個(gè)NSObject對象(可以通過C函數(shù)malloc_size函數(shù)獲得,通過查看OC源碼铁孵,alloc函數(shù)锭硼,也即allocWithZone:中有判斷當(dāng)字節(jié)數(shù)小于16時(shí)就分配16個(gè)字節(jié));而一個(gè)NSObject對象僅使用8個(gè)字節(jié)蜕劝,用于存放成員變量isa指針檀头,(可以通過runtime 的函數(shù)class_getInstanceSize獲得)
………………..
2)對象的isa指針指向哪里?
instance對象的isa指向class對象
class對象的isa指向meta-class對象
meta-class對象指向基類的meta-class對象
(以上的“指向”實(shí)際是通過isa與ISA_MASK常量進(jìn)行&位運(yùn)算的結(jié)果)

3)OC的類信息存放在哪里岖沛?
成員變量暑始、屬性、協(xié)議婴削、實(shí)例方法等信息存放在類對象中廊镜;
類方法存放在元類對象中;
另外唉俗,成員變量的具體值存放在實(shí)例對象中嗤朴。

2、KVO

1)iOS用什么方式實(shí)現(xiàn)對一個(gè)對象的KVO虫溜?(KVO的本質(zhì)是什么雹姊?)
當(dāng)一個(gè)對象的屬性被監(jiān)聽時(shí),runtime會(huì)動(dòng)態(tài)創(chuàng)建一個(gè)新的類衡楞,這個(gè)新的類是原有類的子類(NSKVONotifying_原有類名)吱雏,對象的isa會(huì)指向這個(gè)新類的類對象Class。
當(dāng)修改對象的屬性時(shí),會(huì)調(diào)用 Foundation 中的 _NSSetXXValueAndNotify 函數(shù)歧杏,
這個(gè)函數(shù)會(huì)調(diào)用willChangeValueForKey:镰惦, 然后調(diào)用原有類的setter以修改屬性值,最后調(diào)用didChangeValueForKey:, didChangeValueForKey:內(nèi)部會(huì)觸發(fā)監(jiān)聽器(Observer)的監(jiān)聽方法-observeValueForKeyPath:ofObject:change:contex:

2)如何手動(dòng)觸發(fā)KVO犬绒?
手動(dòng)調(diào)用被監(jiān)聽對象的willChangeValueForKey:方法旺入,讓后調(diào)用didChangeValueForKey:方法,兩個(gè)方法都需要調(diào)用凯力,否則不會(huì)觸發(fā)KVO

3)直接修改成員變量會(huì)觸發(fā)KVO嗎眨业?
不會(huì)。因?yàn)椴粫?huì)走setter方法沮协,就不會(huì)走觸發(fā)KVO的流程

3、KVC

1)通過KVC修改屬性會(huì)觸發(fā)KVO么卓嫂?
會(huì)觸發(fā)KVO慷暂,因?yàn)?setValueForKey:方法會(huì)觸發(fā)willChangeValueForKey: 和 didChangeValueForKey:方法

2)KVC的賦值和取值時(shí)怎樣的?原理是什么晨雳?
賦值:調(diào)用setValue:forkey:方法時(shí)行瑞,會(huì)按 -setKey:,-_setKey: 的順序查找對象的方法餐禁,若查到有實(shí)現(xiàn)其中的方法血久,則調(diào)用;若都沒有實(shí)現(xiàn)帮非,則判斷 +accessInstanceVariableDirectly 方法的返回值氧吐,若為YES,則按 _key, _isKey, key, isKey的順序查到對象的實(shí)例變量末盔,查找到則賦值筑舅。若方法沒有實(shí)現(xiàn),+accessInstanceVariableDirectly返回NO或者實(shí)例變量都不存在陨舱,則會(huì)調(diào)用valueForUndefinedKey:,并報(bào) NSUnknownKeyException 錯(cuò)誤翠拣。
取值:調(diào)用valueForKey: 會(huì)按 -getKey, -key, -isKey, -_key的順序查找方法,若查到有實(shí)現(xiàn)其中的方法游盲,則調(diào)用并返回值误墓;若都沒有實(shí)現(xiàn),則判斷 +accessInstanceVariableDirectly 方法的返回值益缎,若為YES谜慌,則按 _key, _isKey, key, isKey的順序查找成員變量,查找到則將成員變量的值返回链峭。若方法沒有實(shí)現(xiàn)畦娄,+accessInstanceVariableDirectly返回NO或者實(shí)例變量都不存在,則會(huì)調(diào)用valueForUndefinedKey:,并報(bào) NSUnknownKeyException 錯(cuò)誤。

4熙卡、Category

1)Category的使用場合是什么杖刷?
給已有的類擴(kuò)展屬性、方法驳癌、和協(xié)議滑燃;
將一個(gè)類按照功能拆分為不同的分類,方便管理和閱讀代碼

2)Category的實(shí)現(xiàn)原理
Category在編譯完成后的底層結(jié)構(gòu)是 struct category_t 的結(jié)構(gòu)體颓鲜,結(jié)構(gòu)體中存放著Category數(shù)據(jù)(類名表窘,屬性列表,對象方法列表甜滨,類方法列表乐严,協(xié)議列表)
在程序運(yùn)行的時(shí)候,通過runtime將Category數(shù)據(jù)合并到原類的類對象和原類對象中()

4)Category和Class Extension的區(qū)別是什么衣摩?
Category是在運(yùn)行時(shí)將其中的數(shù)據(jù)(如方法等)合并到原類中昂验,
而Class Extension是在編譯時(shí)就將數(shù)據(jù)合并到原類中

5)Category中有l(wèi)oad方法嗎?load方法是什么時(shí)候調(diào)用的艾扮?load 方法能繼承嗎既琴?
·有l(wèi)oad方法
·load方法是在runtime加載類、分類時(shí)調(diào)用的
·load方法可以繼承泡嘴,但一般不會(huì)主動(dòng)調(diào)用load方法甫恩,而是系統(tǒng)自動(dòng)調(diào)用

6)load、initialize方法的區(qū)別什么酌予?它們在category中的調(diào)用的順序磺箕?以及出現(xiàn)繼承時(shí)他們之間的調(diào)用過程?
①區(qū)別:
調(diào)用時(shí)刻:
load是runtime加載類抛虫、分類時(shí)調(diào)用(只會(huì)調(diào)用1次)滞磺;
initialize時(shí)類第1次接受到消息時(shí)調(diào)用,每個(gè)類只會(huì)initialize一次(但是子類沒有實(shí)現(xiàn)initialize方法莱褒,則父類的initialize方法可能會(huì)調(diào)用多次)
調(diào)用方式:
load時(shí)根據(jù)函數(shù)地址直接調(diào)用击困;而initialize時(shí)通過objc_msgSend調(diào)用
②調(diào)用順序
load : a.先調(diào)用類的load:先編譯的類優(yōu)先調(diào)用load;調(diào)用子類的load之前广凸,會(huì)先調(diào)用父類的load
b.后調(diào)用分類的load:先編譯的分類優(yōu)先調(diào)用
initialize: a.先初始化父類調(diào)用父類initialize
b.再初始化子類阅茶,調(diào)用子類的initialize(若子類沒有實(shí)現(xiàn)initialize方法,則最終調(diào)用的的是父類的intialize方法)

5谅海、Block

1)block 的原理是怎樣的脸哀?本質(zhì)是什么?
block 是封裝了函數(shù)調(diào)用和調(diào)用環(huán)境的 OC 對象

2)__block 的作用是什么扭吁?有什么使用注意點(diǎn)撞蜂?
作用:被 __block 修飾的 auto 變量(即非全局變量盲镶、非 static 變量的局部變量),會(huì)被包裝成一個(gè) OC 對象(結(jié)構(gòu)體)蝌诡,變量的實(shí)際值會(huì)作為該結(jié)構(gòu)體的一個(gè)成員溉贿,這樣可以解決在 block 中無法修改 auto 變量的問題。
注意點(diǎn):內(nèi)存管理相關(guān)浦旱,__block 修飾的變量在棧上時(shí)宇色,block 不會(huì)對其強(qiáng)引用;__block 變量被 copy 到堆上時(shí)颁湖,在 MRC 下宣蠕,block 不會(huì)對其強(qiáng)引用,在 ARC 下甥捺,會(huì)根據(jù)變量的其他修飾關(guān)鍵字進(jìn)行強(qiáng)引用或弱引用抢蚀。

3)block的屬性修飾詞為什么是 copy?使用block有哪些使用注意镰禾?
為什么是 copy:block 沒有被 copy 之前思币,是在內(nèi)存中的棧上或者全局區(qū),生命周期由系統(tǒng)管理羡微;而 copy 之后會(huì)被 copy 到堆上,此時(shí) block 生命周期由代碼管理惶我。
使用注意:循環(huán)引用問題妈倔,會(huì)導(dǎo)致內(nèi)存泄漏。

4)block 在修改 NSMutableArray (添加或移除元素)绸贡,需不需要添加 __block盯蝴?
不需要。因?yàn)閷?NSMutableArray 添加或移除元素不需要修改變量的值听怕。

Runtime

1捧挺、消息機(jī)制

1)講一下 OC 的消息機(jī)制
OC 對象調(diào)用方法底層轉(zhuǎn)為 objc_msgSend 函數(shù)調(diào)用,即給對象(消息接受者)發(fā)送一條消息(selector 方法名)尿瞭;
objc_msgSend 函數(shù)底層實(shí)現(xiàn)大致分為三大階段:消息發(fā)送闽烙,動(dòng)態(tài)方法解析,消息轉(zhuǎn)發(fā)声搁;
消息發(fā)送:通過對象的 isa 指針找到類對象或元類對象(取決于消息接受者是實(shí)例對象還是類對象黑竞,這里假設(shè)是實(shí)例對象,類對象的處理類似)疏旨,依次在類對象中的方法緩存列表和方法列表中查找消息的 selector 方法名很魂,若找到則直接調(diào)用方法,否則繼續(xù)從父類的方法列表中查找檐涝,一直找到基類為止遏匆;若查找到基類也沒有找到方法法挨,則進(jìn)入動(dòng)態(tài)方法解析階段;
動(dòng)態(tài)方法解析:實(shí)現(xiàn) -resolveInstanceMethod:(SEL)sel 方法幅聘,并調(diào)用 runtime 的方法 class_addMethod凡纳,為對象動(dòng)態(tài)地添加一個(gè)方法,然后再次進(jìn)入消息發(fā)送階段喊暖,并標(biāo)記已經(jīng)嘗試過動(dòng)態(tài)方法解析惫企;若添加了方法,則直接調(diào)用陵叽;若沒有添加狞尔,則進(jìn)入消息轉(zhuǎn)發(fā)階段;
消息轉(zhuǎn)發(fā):實(shí)現(xiàn) -forwardingTargetForSelector: 方法巩掺,返回一個(gè)新的對象做為消息接受者偏序,并調(diào)用 objc_msgSend 方法;若沒有返回新的對象而是返回 nil胖替,則會(huì)調(diào)用 -methodSignatureForSelctor: 方法研儒,若此方法返回一個(gè)方法簽名,則進(jìn)入 -forwardInvocation: 方法独令,可以做任何處理端朵;若返回 nil,則會(huì)報(bào)經(jīng)典錯(cuò)誤 unrecognized selector sent to instance xxxxx

2)消息轉(zhuǎn)發(fā)機(jī)制流程
同問題1)

3)什么是Runtime燃箭?平時(shí)項(xiàng)目中有用過么冲呢?
Runtime:OC 是一門動(dòng)態(tài)性很強(qiáng)的語言,很多操作允許推遲到程序運(yùn)行時(shí)再執(zhí)行招狸;
OC 的動(dòng)態(tài)性是由 Runtime 來實(shí)現(xiàn)的敬拓,Runtime 是一套 C 語言的 API,封裝了很多動(dòng)態(tài)性相關(guān)的函數(shù)裙戏;
平時(shí)編寫的 OC 代碼乘凸,底層都是轉(zhuǎn)換為了 Runtime 的 API 進(jìn)行調(diào)用。
用途:給分類添加屬性實(shí)現(xiàn)(關(guān)聯(lián)對象 AssociateObject)累榜;
方法交換(method_exchange)营勤;
遍歷類的所有成員變量(歸檔解檔,獲取私有成員如textField._placeholderLabel壹罚,字典轉(zhuǎn)模型)
利用消息轉(zhuǎn)發(fā)機(jī)制冀偶,監(jiān)測方法找不到的問題;
...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渔嚷,一起剝皮案震驚了整個(gè)濱河市进鸠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌形病,老刑警劉巖客年,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霞幅,死亡現(xiàn)場離奇詭異,居然都是意外死亡量瓜,警方通過查閱死者的電腦和手機(jī)司恳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绍傲,“玉大人扔傅,你說我怎么就攤上這事√瘫” “怎么了猎塞?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長杠纵。 經(jīng)常有香客問我荠耽,道長,這世上最難降的妖魔是什么比藻? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任铝量,我火速辦了婚禮,結(jié)果婚禮上银亲,老公的妹妹穿的比我還像新娘慢叨。我一直安慰自己,他們只是感情好务蝠,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布拍谐。 她就那樣靜靜地躺著,像睡著了一般请梢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上力穗,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天毅弧,我揣著相機(jī)與錄音,去河邊找鬼当窗。 笑死够坐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的崖面。 我是一名探鬼主播元咙,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼巫员!你這毒婦竟也來了庶香?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對情侶失蹤简识,失蹤者是張志新(化名)和其女友劉穎赶掖,沒想到半個(gè)月后感猛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奢赂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年陪白,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膳灶。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咱士,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出轧钓,到底是詐尸還是另有隱情序厉,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布聋迎,位于F島的核電站脂矫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏霉晕。R本人自食惡果不足惜庭再,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望牺堰。 院中可真熱鬧拄轻,春花似錦、人聲如沸伟葫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筏养。三九已至斧抱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渐溶,已是汗流浹背辉浦。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茎辐,地道東北人宪郊。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像拖陆,于是被迫代替她去往敵國和親弛槐。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344