大家好吁恍,我是面試聊iOS的程序員锅锨。
這篇文章將和大家分享面試iOS時聊RunTime一般都可以聊些什么雕欺。
抖音搜索 面試聊iOS 觀看視頻版
相關文章鏈接
面試聊iOS:內存管理
面試聊iOS:RunTime(一)
面試聊iOS:RunTime(二)
面試聊iOS:Block
面試聊iOS:多線程
面試聊iOS:RunLoop
面試聊iOS:性能優(yōu)化
OC是一門動態(tài)語言
動態(tài)語言是指程序可以在運行時可以改變其結構:添加新的函數富雅、屬性蒲犬,刪除已有的函數宜狐、屬性等結構上的變化势告,在運行時做類型的檢查。
編譯時:源代碼被編譯成機器可以識別的代碼的過程抚恒。
運行時:用戶可以運行編譯過的程序咱台,程序運行的過程。
OC的動態(tài)性由runtime支持的俭驮。
runtime是一個C語言的庫回溺,提供API創(chuàng)建類、添加方法混萝、刪除方法遗遵、交換方法等。
id逸嘀、instanceType
id
使用id修飾的對象是動態(tài)類型车要,只是簡單的聲明了指向對象的指。
編譯時不做類型檢查崭倘,可以發(fā)送任何信息給id類型的對象
instanceType
表示某個方法返回未知類型的OC對象
非關聯類型的方法返回所在類的類型
instancetype可以返回和方法所在類相同類型的對象翼岁,id只能返回未知類型的對象
instancetype只能作為返回值,不能像id一樣作為參數
關聯返回類型
- 類方法中司光,以alloc登澜、new開頭
- 實例方法中,以autorelease飘庄、init、retain购撼、或self開頭
當方法的返回值為id類型跪削,方法不會返回一個類型不明的對象,會返回一個方法所在類類型的對象迂求。
非關聯返回類型
- 類方法中碾盐,不以alloc、new開頭
- 實例方法中揩局,不以autorelease毫玖、init、retain、或self開頭
當方法的返回值為id付枫,方法會返回一個類型不明的對象烹玉;可以用instancetype作為方法的返回值的類型,返回一個方法所在類類型的對象阐滩。
NSObject *
聲明類指向NSObject類型對象的指針二打,編譯時要做類型檢查
NSObject是OC中的基類,絕大多數類都繼承與NSObject
id<NSObject>
也是一個指針掂榔,要求指向的類型要實現NSObject protocol
NSObject继效、NSProxy類實現了NSObject接口,id<NSObject>可以指向它們
OC對象的本質
OC對象本身是一個結構體装获,這個結構體只有一個isa指針
任何數據結構瑞信,只要在恰當的位置有個指針指向一個class,那么它就可以被認為是一個對象穴豫。
NSObject對象內存大小
64bit下凡简,bool、signed char绩郎、unsigned char 占1個字節(jié)潘鲫;
short、unsigned short 占2個字節(jié)肋杖,int溉仑、unsigned int、float占4個字節(jié)状植;
long浊竟、unsigned long、 long long津畸、double占8個字節(jié)振定。
NSObject占8個字節(jié)
結構體內成員按自身長度自對齊
對象內存申請的時候按8字節(jié)對齊,開辟內存時按16字節(jié)對齊
isa指針(is a what?)
objc_object *id;
struct objc_object {
Class isa;
?}
objc_class *Class;
struct objc_class {
super_class,
name,
version,
info,
instance_size,
ivars,
methodLists,
cache,
protocols
}
isa指向流程
實例對象isa指向類對象
類對象isa指向元類
類對象superClass指向父類指向的類對象
所有元類isa指向NSObject對象的元類(根元類)
根元類isa指向自己
根元類的superClass指向NSObject的類對象
元類的superClass指向對應父類的元類
消息發(fā)送機制
在OC中肉拓,對象調用方法其實是對象接收消息后频,消息的發(fā)送采用“動態(tài)綁定”的機制,具體調用哪個方法知道運行時才能確定暖途,確定后才會去執(zhí)行綁定的代碼
OC對象調用方法在運行時會被轉化為 void objc_msgSend(id self, SEL cmd...)
SEL:方法名?IMP:指向方法實現的函數指針
消息發(fā)送流程
- 根據消息接收者的isa確定自己所屬的類卑惜,先在類的_x001D_cache和MethodLists中從上向下查找IMP;
- 如果本類中沒有找到驻售,則會根據本類的superClass指針露久,沿著繼承體系繼續(xù)向上查找(向父類查找);
- 如果向父類查找都沒有找到欺栗,則會進入消息轉發(fā)流程
消息轉發(fā)流程
- 動態(tài)解析
+ (BOOL)resolveInstanceMethod:(SEL)selector;
+ (BOOL)resolveIClassMethod:(SEL)selector;
- 備用接收者
- (id)forwardingTargetForSelector:(SEL)selector;
- 消息重定向
- (void)forwardInvocation:(NSInvocation *)anInvocation毫痕;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector征峦;
最后消息未能處理的時候,還會調用
- (void)doesNotRecognizeSelector:(SEL)aSelector拋出異常
Method Swizzing(方法交換)
Method Swizzing是發(fā)生在運行時的消请,主要用于在運行時將兩個Method進行交換.
先給要替換的方法的類添加一個Category栏笆,然后在Category中的+(void)load方法中添加Method Swizzling方法,我們用來替換的方法也寫在這個Category中梯啤。
Swizzling應該總在+load中執(zhí)行竖伯,load類方法是程序運行時這個類被加載到內存中就調用的一個方法,執(zhí)行比較早因宇,并且不需要我們手動調用
Swizzling應該總是在dispatch_once中執(zhí)行七婴,避免被多次執(zhí)行
Method Swizzing應用
頁面統(tǒng)計
交換controller view的生命周期方法事件統(tǒng)計、防止按鈕短時間內重復點擊
交換UIControl sendAction:to:forEvent方法交換delegate的方法
hook setDelegate方法察滑,最好加上是否實現了delegate的方法的判斷防止數組越界崩潰
hook objectAtIndex打厘,需要獲取到類簇的真身