diff --git a/README.md b/README.md index 8f31083..e84cf62 100644 --- a/README.md +++ b/README.md @@ -108,37 +108,50 @@ void run(id self, SEL _cmd, NSNumber *metre) {

消息转发 / ForwardMessage

```objc -// 指定方法签名,若返回 nil,则不会进入下一步,而是无法处理消息 -- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { - if ([NSStringFromSelector(aSelector) isEqualToString:@"stoke"]) { - return [NSMethodSignature signatureWithObjCTypes:"v@:"]; - } +#pragma mark - 实例方法 + +// 第一步 +// 在没有找到方法时,会先调用此方法,可用于动态添加方法 +// 返回 YES 表示相应 selector 的实现已经被找到并添加到了类中,否则返回 NO + ++ (BOOL)resolveInstanceMethod:(SEL)sel { + return YES; +} + +// 第二步 +// 如果第一步的返回 NO 或者直接返回了 YES 而没有添加方法,该方法被调用 +// 在这个方法中,我们可以指定一个可以返回一个可以响应该方法的对象 +// 如果返回 self 就会死循环 + +- (id)forwardingTargetForSelector:(SEL)aSelector { + return nil; +} - return [super methodSignatureForSelector:aSelector]; +// 第三步 +// 如果 `forwardingTargetForSelector:` 返回了 nil,则该方法会被调用,系统会询问我们要一个合法的『类型编码(Type Encoding)』 +// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html +// 若返回 nil,则不会进入下一步,而是无法处理消息 + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { + return [NSMethodSignature signatureWithObjCTypes:"v@:"]; } // 当实现了此方法后,-doesNotRecognizeSelector: 将不会被调用 // 如果要测试找不到方法,可以注释掉这一个方法 // 在这里进行消息转发 - (void)forwardInvocation:(NSInvocation *)anInvocation { - // 我们还可以改变方法选择器 [anInvocation setSelector:@selector(touch)]; // 改变方法选择器后,还需要指定是哪个对象的方法 [anInvocation invokeWithTarget:self]; } -- (void)doesNotRecognizeSelector:(SEL)aSelector { - NSLog(@"无法处理消息:%@", NSStringFromSelector(aSelector)); +- (void)touch { + NSLog(@"Cat 没有实现 -stoke 方法,并且成功的转成了 -touch 方法"); } -+ (void)touch { - NSLog(@"Cat 没有实现 stoke 方法,并且成功的转成了 touch 方法"); -} - -+ (void)stoke { - Cat *carson = [[Cat alloc] init]; - [Cat performSelector:@selector(touch) withObject:nil afterDelay:0]; +- (void)doesNotRecognizeSelector:(SEL)aSelector { + NSLog(@"无法处理消息:%@", NSStringFromSelector(aSelector)); } ``` @@ -243,7 +256,7 @@ void run(id self, SEL _cmd, NSNumber *metre) { 觉得还有其它常用的 Runtime 用法没有讲到?欢迎 Pull Request! -或者懒得动手想看看大家的思路?没问题,提个 [issue](https://github.com/Tuccuay/RuntimeSummary/issues) ! +或者懒得动手想看看大家的思路?没问题,提个 [issue](https://github.com/Tuccuay/RuntimeSummary/issues/new) ! 觉得看了这个 Playground 豁然开朗?来 Star 一个吧!