大家好绿店,我是面試聊iOS的程序員理茎。
這篇文章將和大家分享面試iOS時(shí)聊RunTime一般都可以聊些什么。
視頻版:抖音搜索 面試聊iOS
相關(guān)文章鏈接
面試聊iOS:內(nèi)存管理
面試聊iOS:RunTime(一)
面試聊iOS:RunTime(二)
面試聊iOS:Block
面試聊iOS:多線程
面試聊iOS:RunLoop
面試聊iOS:性能優(yōu)化
Category
objc_category *Category;
struct objc_category {
category_name,
class_name,
instance_methods,
class_methods,
protocols
}
在程序運(yùn)行時(shí)
實(shí)例方法整合到主類中
類方法整合到元類中
協(xié)議同時(shí)整合到主類和元類中
在類的+laod方法中可以調(diào)用category里聲明的方法嗎?
可以换淆,因?yàn)楦郊覥ategory到類的工作先于+load方法的執(zhí)行
類和category的+load方法調(diào)用的順序
先類哗总,后category。而各個(gè)category的+load方法按照編譯的順序執(zhí)行
關(guān)聯(lián)對(duì)象存在哪倍试?
所有的關(guān)聯(lián)對(duì)象都由AssociationsManager管理讯屈,AssociationsManager里面由一個(gè)靜態(tài)AssociationsHashMap來存儲(chǔ)所有的關(guān)聯(lián)對(duì)象的。
在category里可以添加屬性嗎县习?
category中只能添加方法涮母,不能添加實(shí)例變量。類的內(nèi)存大小是在編譯時(shí)確定的躁愿,而category是在運(yùn)行時(shí)被添加的叛本,此時(shí)再添加實(shí)例變量會(huì)破壞內(nèi)存結(jié)構(gòu)。
在category中添加屬性彤钟,通過關(guān)聯(lián)對(duì)象實(shí)現(xiàn)setter来候、getter方法。
類和category的同名方法調(diào)用的順序
category并不是完全替換掉主類的同名方法逸雹,只是類的方法列表中會(huì)出現(xiàn)名字一樣的方法且category的方法會(huì)排在前面营搅,多個(gè)category中的同名方法按編譯的順序排。runtime查找方法按照順序梆砸,一旦找到就return转质。
遍歷類的方法列表,列表里最后一個(gè)同名的方法帖世,即是原方法峭拘。
category
- 運(yùn)行時(shí)決議
- 有單獨(dú)的.h和.m文件
- 可以為系統(tǒng)類添加分類
- 看不到源碼的類可以添加分類
- 只能添加方法,不能添加實(shí)例變量
extension
- 編譯時(shí)決議
- 以聲明的方式存在狮暑,寄生于主類.m文件
- 不可以為系統(tǒng)類添加extension
- 沒有.m源碼的類不可以extension
- 可以添加方法鸡挠,可添加實(shí)例變量,默認(rèn)為@private
KVC
是一種可以通過key來訪問類屬性的機(jī)制搬男。而不是通過調(diào)用Setter拣展、Getter方法訪問。
可以在運(yùn)行時(shí)動(dòng)態(tài)訪問和修改對(duì)象的屬性
// 賦值
[person1 setValue:@"jack" forKey:@"name"];
// 取值
NSString *name = [person1 valueForKey:@"name"];
forKeyPath 是對(duì)更“深層”的對(duì)象進(jìn)行訪問缔逛。如數(shù)組的某個(gè)元素备埃,對(duì)象的某個(gè)屬性。
[myModel setValue:@"beijing" forKeyPath:@"address.city"];
// 返回所有對(duì)象的name屬性值
NSArray *names = [array valueForKeyPath:@"name"];
setValue:ForKey:
- 按照setKey褐奴、_setKey的順序查找方法按脚,找到了就傳遞參數(shù),調(diào)用方法
- 如果沒找到敦冬,則查看accessInstanceVariableDirectly方法的返回值辅搬,如果為NO(默認(rèn)是YES)就不再繼續(xù)往下執(zhí)行,直接調(diào)用setValue:forUndefinedKey拋出NSUnknownKeyException異常
- 如果返回值為YES脖旱,則按照_key堪遂、_isKey介蛉、key、isKey的順序查找成員變量溶褪,找到了就直接賦值
- 如果沒找到币旧,則調(diào)用setValue:forUndefinedKey拋出異常
valueForKey:
- 按照getKey、_getKey的順序查找方法猿妈,找到了就直接調(diào)用方法
- 如果沒找到吹菱,則查看accessInstanceVariableDirectly方法的返回值,如果為NO(默認(rèn)是YES)就不再繼續(xù)往下執(zhí)行彭则,直接調(diào)用value:forUndefinedKey拋出NSUnknownKeyException異常
- 如果返回值為YES毁葱,則按照_key、_isKey贰剥、key倾剿、isKey的順序查找成員變量,找到了就直接取值
- 如果沒找到蚌成,則調(diào)用value:forUndefinedKey拋出異常
KVO
KVO:key value observing前痘,鍵值監(jiān)聽,可以監(jiān)聽對(duì)象某個(gè)屬性值的變化
- 給對(duì)象添加監(jiān)聽
- 通過runtime動(dòng)態(tài)創(chuàng)建一個(gè)子類担忧,修改對(duì)象的isa指向子類
- 子類重寫set方法芹缔,內(nèi)部執(zhí)行順序
willChangeValueForKey
[super setKey]
didChangeValueForKey
在didChangeValueForKey中調(diào)用KVO的回調(diào)方法:observeValueForKeyPath:ofObject:change:context:
歸檔解檔(NSCoding)
歸檔與解檔是iOS中一種序列化與反序列化的方式。
對(duì)象要實(shí)現(xiàn)序列化需要遵循NSCoding協(xié)議瓶盛。
通過class_copyIvarList獲得對(duì)象的屬性列表
通過ivar_getName(ivar)獲取到屬性的C字符串名稱
NSString *key = [NSString stringWithUTF8String:name];轉(zhuǎn)成對(duì)應(yīng)的OC名稱
利用KVC進(jìn)行歸檔 [corder encodeObject: [self valueForKey:key] forKey: key];
解檔 id value = [coder decodeObjectForKey];
利用KVC進(jìn)行賦值[self setValue:value ForKey:key];