前言
上章說到系統(tǒng)沒有找到對應(yīng)的方法實現(xiàn)時會進(jìn)入resolveInstanceMethod
動態(tài)決議流程。而實際消息流程中有三層容錯機(jī)制:動態(tài)決議->快速轉(zhuǎn)發(fā)->慢速轉(zhuǎn)發(fā)。
動態(tài)決議
if (! cls->isMetaClass()) {
// try [cls resolveInstanceMethod:sel]
resolveInstanceMethod(inst, sel, cls);
}
else {
// try [nonMetaClass resolveClassMethod:sel]
// and [cls resolveInstanceMethod:sel]
resolveClassMethod(inst, sel, cls);
if (!lookUpImpOrNil(inst, sel, cls)) {
resolveInstanceMethod(inst, sel, cls);
}
}
類方法的查找與實例方法的查找不同龄句。
類方法的查找:
- 先找類的
resolveClassMethod
- 再找元類及父類的
resolveInstanceMethod
原因:因為類方法實際是存放在元類的實例方法张症。
動態(tài)決議流程
創(chuàng)建一個Person
類,定義- (void)test1
與+(void)test2
不實現(xiàn)产还。
調(diào)用執(zhí)行這兩個方法砖瞧。
在Person
中實現(xiàn):
運(yùn)行結(jié)果如圖:
快速轉(zhuǎn)發(fā)流程
當(dāng)動態(tài)決議未處理時,會進(jìn)入快速轉(zhuǎn)發(fā)流程- (id)forwardingTargetForSelector:(SEL)aSelector;
官方文檔介紹
快速轉(zhuǎn)發(fā)流程及給消息指定一個接收者嘲恍。
定義一個
Teaher
類實現(xiàn)test1
方法,然后再Person
中實現(xiàn):
- (id)forwardingTargetForSelector:(SEL)aSelector {
NSLog(@"%@", NSStringFromSelector(aSelector));
return [Teacher alloc];
}
執(zhí)行結(jié)果如圖:
慢速轉(zhuǎn)發(fā)
當(dāng)快速轉(zhuǎn)發(fā)也不做處理時,進(jìn)入慢速轉(zhuǎn)發(fā)流程,系統(tǒng)不會做過多的處理,會將其當(dāng)做事務(wù)拋出,誰需要誰去處理該方法足画。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
NSLog(@"%@", anInvocation);
}
如果誰需要這個方法,只需指定
target
- (void)forwardInvocation:(NSInvocation *)anInvocation {
anInvocation.target = [Teacher alloc];
[anInvocation invoke];
}
ps:不執(zhí)行,系統(tǒng)也不會崩潰,但浪費(fèi)了性能。
整個容錯機(jī)制如圖: