OC中的方法调用其实是runtime时才决定的,调用一个对象的方法,等于给其发消息,调用一个对象不存在的方法,不会立马crash,其实系统会跟我们几次机会,如果我们都错过了,才会crash
其流程大概五如下图所示:
步骤大体是:
1.在方法列表中查找,如果有,给其发信号调用
2.尝试进行动态解析,也就是Get和Set一类方法,具体看@dynamic
3.尝试快速消息转发,(下面解说)
4.尝试标准消息转发,(下面解说)
5.抛出异常
先来说说第3步(快速消息转发):
快速消息转发需要复写forwardingTargetForSelector,意思是说,本类实现不了的方法,可以转发给别的类去实现
- (id)forwardingTargetForSelector:(SEL)aSelector
{
CHKeyChain *other = [CHKeyChain new];
if ([other forwardingTargetForSelector:aSelector]) {
return other;
}else{
return [super forwardingTargetForSelector:aSelector];
}
}
这样如果本类中没有的方法,就会去CHKeyChain中尝试查找,如果有,则返回CHKeyChain对象,让其执行,这样就实现了快速消息转发
再来说说第4步(标准消息转发):
这个就略费劲一点,需要实现methodSignatureForSelector和forwardInvocation
具体如:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];
if (signature==nil) {
signature = [someObj methodSignatureForSelector:aSelector];
}
return signature;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
SEL seletor = [anInvocation selector];
if ([someObj respondsToSelector:seletor]) {
[anInvocation invokeWithTarget:someObj];
}
}
如果以上两步都没找到转发对象,那就会调NSobject的forwardInvocation方法,
起实现大概如下:
- (void) forwardInvocation: (NSInvocation*)anInvocation
{
[self doesNotRecognizeSelector:[anInvocation selector]];
return;
}
- (void) doesNotRecognizeSelector: (SEL)aSelector
{
[NSException raise: NSInvalidArgumentException
format: @"%s does not recognize %s",
object_get_class_name(self), sel_get_name(aSelector)];
}
总结:
1.可以用消息转发这一特性来实现“多重继承”
2.快速消息转发优先与标准消息转发,速度也更快些
赶紧自己写个demo 耍耍吧,enjoy it