*main.m
PersonA *personA = [[PersonA alloc]init];
[personA speechJapan];
- PersonB.h
- (void)speechJapan;
- PersonB.m
- (void)speechJapan{
NSLog(@"speechJapan");
}
- PersonA.h
- (void)speechEnglish;
- (void)speechJapan;
- PersonA.m
- (void)speechEnglish{
NSLog(@"speechEnglist");
}
// 此方法不是方法的實(shí)現(xiàn)捞魁,需要進(jìn)行轉(zhuǎn)化
- (void)speechNewLan{
NSLog(@"speechNewLan");
}
// 將方法轉(zhuǎn)換成方法的實(shí)現(xiàn)IMP
IMP convertToIMP(){
return class_getMethodImplementation([PersonA class], @selector(speechNewLan));
}
/* 當(dāng)未找到speechJapan時(shí)钾菊,首先調(diào)用此方法,使有機(jī)會(huì)添加一個(gè)實(shí)現(xiàn)的方法
如果添加了方法并且放回了Yes磺箕,則運(yùn)行時(shí)系統(tǒng)會(huì)啟用一次消息發(fā)送的過(guò)程稽屏。如果返回為NO,
運(yùn)行時(shí)系統(tǒng)則進(jìn)入到下一步扮宠,消息轉(zhuǎn)發(fā)(Message Forwarding)
*/
// 消息派發(fā)
+ (BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(speechJapan)) {
class_addMethod(self, sel, convertToIMP(), "");
return YES;
}
return NO;
}
/*實(shí)現(xiàn)此方法,運(yùn)行時(shí)系統(tǒng)就會(huì)調(diào)用次方法诫欠,將消息轉(zhuǎn)發(fā)給其他指定的對(duì)象涵卵,
比如轉(zhuǎn)發(fā)給PersonB的對(duì)象
注:只要返回的對(duì)象不是nil或self浴栽,消息發(fā)送的整個(gè)過(guò)程就會(huì)啟動(dòng)
發(fā)送的對(duì)象變?yōu)橹付ǚ祷氐膶?duì)象,比如PersonB轿偎。如果返回的是nil或self典鸡,則進(jìn)行下一步轉(zhuǎn)發(fā)操作
*/
- (id)forwardingTargetForSelector:(SEL)aSelector{
if (aSelector == @selector(speechJapan)) {
PersonB *pB = [[PersonB alloc] init];
return pB;
}
return [super forwardingTargetForSelector:aSelector];
}
// 消息轉(zhuǎn)發(fā)第二步 Mormal forwrading
/* 獲取方法簽名
調(diào)用此方法獲取函數(shù)的參數(shù)和返會(huì)類型,如果此方法返回nil
Runtime則會(huì)發(fā)出doseNotRecognizeSelector: 消息掛掉程序
如果返回一個(gè)函數(shù)簽名,Runtime則會(huì)創(chuàng)建一個(gè)NSINvocation對(duì)象坏晦,調(diào)用ForwradInvacation:
發(fā)送消息給對(duì)象
*/
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSMethodSignature *sign = [[PersonB class] instanceMethodSignatureForSelector:aSelector];
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
// 實(shí)現(xiàn)消息的轉(zhuǎn)發(fā)
/*
NSInvocation 實(shí)際上是對(duì)一個(gè)消息的描述萝玷,包括selector極其參數(shù)等信息
所以可以在此方法中修改NSInvocation對(duì)象,然后調(diào)用invokeWithTarget:消息給對(duì)象
*/
- (void)forwardInvocation:(NSInvocation *)anInvocation{
SEL sel = anInvocation.selector;
PersonB *pB = [[PersonB alloc] init];
if ([pB respondsToSelector:sel]) {
[anInvocation invokeWithTarget:pB];
}else{
[self doesNotRecognizeSelector:sel];
}
}