oc中調用方法其實就是向對象發(fā)送消息赴捞,在編譯Objective-C函數(shù)調用的語法時,會被翻譯成一個C的函數(shù)調用:objc_msgSend(),例如:
那么掰派,objc_msgSend又做了哪些事呢碗淌?碎罚,以[object foo]為例:
1.通過object的isa指針找到它的class
2.在class的method_list中找到foo
3.如果class中沒找到foo,則繼續(xù)往他的superclass中查找
4.一旦找到foo這個函數(shù)宫峦,就去執(zhí)行對應的方法實現(xiàn)(IMP)
NSMethodSignature(方法簽名)
方法簽名:用語記錄一個方法的參數(shù)和返回值類型的類屎飘。類似于objc_method_description結構體。方法簽名是用于初始化NSInvocation用的。
用于記錄一個消息(方法)的接收者(target)方法名(SEL)參數(shù)類型,參數(shù)等信息,包含執(zhí)行該消息方法的類沐批。
此類類似于結構體Method。
他提供了- (void)invokeWithTarget:(id)target;調用對象中的方法九孩。類似于id method_invoke(id receiver, Method m, …) 函數(shù)先馆。
注意:NSMethodSignature,NSInvocation一般我們都是用語消息轉發(fā)時候用到躺彬。正常我們用的比較少煤墙。
二梅惯、動態(tài)方法決議與消息轉發(fā)
消息轉發(fā)機制基本上分為三個步驟:
1. 動態(tài)方法解析:- (BOOL)resolveInstanceMethod:(SEL)sel;+ (BOOL)resolveClassMethod:(SEL)sel 返回添加新方法并YES
2. 備用接收者
-(id)forwardingTargetForSelector:(SEL)aSelector?
如果一個對象實現(xiàn)了這個方法仿野,并返回一個非nil的對象铣减,則返回的對象會作為消息的新接收者,且消息會被分發(fā)到這個對象脚作。當然這個對象不能是self自身葫哗,否則就是出現(xiàn)無限循環(huán)。當然球涛,如果我們沒有指定相應的對象來處理aSelector劣针,則應該調用父類的實現(xiàn)來返回結果。
3. 完整轉發(fā)
如果在上一步還不能處理未知消息亿扁,則唯一能做的就是啟用完整的消息轉發(fā)機制了捺典。
此時會調用以下方法:
-(void)forwardInvocation:(NSInvocation*)anInvocation
由于NSInvocation的初始化需要有一個方法簽名NSMethodSignature,所以我們還需要實現(xiàn)下面的方法从祝,該方法的返回值用于初始化NSInvocation的辣苏。
-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector
methodSignatureForSelector用來生成方法簽名,這個簽名就是給forwardInvocation中的參數(shù)NSInvocation調用的哄褒。