今天忽然又兴趣看了下 NSObject的头文件,发现其中的消息转发机制还不甚了解,因此在 debug 调试了解以后,写下此文章留做记录 函数
- (id)forwardingTargetForSelector:(SEL)aSelector; - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector; + (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector; - (void)forwardInvocation:(NSInvocation *)anInvocation; - (void)doesNotRecognizeSelector:(SEL)aSelector;调用顺序如上面函数顺序
当使用以下函数调用 spa
[someObj method1];//方式1 [someObj performSelector:@selector(method1)];//方式2若是 someObj没有实现 method1函数
runtime 将会调用 debug
- (id)forwardingTargetForSelector:(SEL)aSelector { if ([SomeObj respondsToSelector:aSelector]) { return someObj; } return nil; }
若是 SomeObj 可以响应 aSelector,咱们就将此消息转发到 someObj. 调试
若是SomeObj 不能响应,函数返回了 nil code
此时 runtime system将调用 orm
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSMethodSignature *signature = [super methodSignatureForSelector:aSelector]; if (signature == nil) { signature = [OtherObj instanceMethodSignatureForSelector:aSelector]; } return signature; }
若是父类没有实现此SEL,就询问 OtherObj 是否实现此 SEL get
若是实现就返回NSMethodSignature cmd
不然就返回 nil,此时 runtime system就会调用 it
- (void)doesNotRecognizeSelector:(SEL)aSelector { NSLog(@"%@ %@",NSStringFromClass(self.class),NSStringFromSelector(_cmd)); }表示没有实现此函数,并抛出NSInvalidArgumentException 异常
能够在此函数中作程序最后的处理 io
说回去,若是OtherObj实现了此函数,则 runtime system 会调用
- (void)forwardInvocation:(NSInvocation *)anInvocation { if ([OtherObj instancesRespondToSelector:[anInvocation selector]]) [anInvocation invokeWithTarget:otherObj]; else [super forwardInvocation:anInvocation]; }这样写是为了让父类的转发不被覆盖,这里若是不调用
[anInvocation invokeWithTarget:otherObj];
将不会真正调用函数
到此,转发的方式与过程叙述完毕