objc 消息转发

今天突然又兴趣看了下 NSObject的头文件,发现其中的消息转发机制还不甚了解,所以在 debug 调试了解之后,写下此文章留作记录

- (id)forwardingTargetForSelector:(SEL)aSelector;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector;
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (void)doesNotRecognizeSelector:(SEL)aSelector;
调用顺序如上面函数顺序

当使用如下函数调用

[someObj method1];//方式1
[someObj performSelector:@selector(method1)];//方式2
如果 someObj没有实现 method1函数

runtime 将会调用

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if ([SomeObj respondsToSelector:aSelector]) {
        return someObj;
    }
    
    return nil;
}

如果 SomeObj 能够响应 aSelector,我们就将此消息转发到 someObj.

如果SomeObj 不能响应,函数返回了 nil

此时 runtime system将调用

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
    if (signature == nil) {
        signature = [OtherObj instanceMethodSignatureForSelector:aSelector];
    }
    
    return signature;
}

如果父类没有实现此SEL,就询问 OtherObj 是否实现此 SEL

如果实现就返回NSMethodSignature

否则就返回 nil,此时 runtime system就会调用

- (void)doesNotRecognizeSelector:(SEL)aSelector
{
    NSLog(@"%@ %@",NSStringFromClass(self.class),NSStringFromSelector(_cmd));
}
表示没有实现此函数,并抛出NSInvalidArgumentException 异常

可以在此函数中做程序最后的处理

说回去,如果OtherObj实现了此函数,则 runtime system 会调用

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([OtherObj instancesRespondToSelector:[anInvocation selector]])
        [anInvocation invokeWithTarget:otherObj];
    else
        [super forwardInvocation:anInvocation];
}
这样写是为了让父类的转发不被覆盖,这里如果不调用

[anInvocation invokeWithTarget:otherObj];

将不会真正调用函数

到此,转发的方式与过程叙述完毕


你可能感兴趣的:(ios,Objective-C,objC,NSObject,消息转发)