在oc里面,发送消息给一个并不响应这个方法的对象,是合法的。apple设计这种机制的原因是用来模拟多重继承(oc原生是不支持多重继承的)。消息转发的大致过程是:
1、查找该类及其父类的cache和方法分发表,找不到的情况下执行第2步。
2、执行+(BOOL)resolveInstanceMethod:(SEL)aSEL方法。
3、接下来 Runtime 会调用 – (id)forwardingTargetForSelector:(SEL)aSelector 方法。
这就给了程序员第二次机会,如果你没办法在自己的类里面找到替代方法,你就重载这个方法,然后把消息转给其他的Object。
4、最后,Runtime 会调用 – (void)forwardInvocation:(NSInvocation *)anInvocation 这个方法。NSInvocation 其实就是一条消息的封装。如果你能拿到 NSInvocation,那你就能修改这条消息的 target, selector 和 arguments。
例如:
void fooMethod(id obj, SEL _cmd)
{
NSLog(@"Doing Foo");
}
//重载resolveInstanceMethod
+(BOOL)resolveInstanceMethod:(SEL)aSEL
{
if(aSEL == @selector(doFoo:)){
class_addMethod([self class],aSEL,(IMP)fooMethod,"v@:");
return YES;
}
return [super resolveInstanceMethod];
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if(aSelector == @selector(mysteriousMethod:)){
return alternateObject;
}
return [super forwardingTargetForSelector:aSelector];
}
-(void)forwardInvocation:(NSInvocation *)invocation
{
SEL invSEL = invocation.selector;
if([altObject respondsToSelector:invSEL]) {
[invocation invokeWithTarget:altObject];
} else {
[self doesNotRecognizeSelector:invSEL];
}
}