利用OC对象的消息重定向forwardingTargetForSelector方法构建高扩展性的滤镜功能

 在OC中,当像一个对象发送消息,而对象找到消息后,从它的类方法列表,父类方法列表,一直找到根类方法列表都没有找到与这个选择子对应的函数指针。那么这个对象就会触发消息转发机制。

OC对象的继承链和isa指针链如图:

 

消息转发流程如下:
1.先调用实例方法resolveInstanceMethod
如果作者在这里使用runtime动态添加对应的方法,并且返回yes。就万事大吉。对象找到了处理的方法,
并且将这个新增的方法添加到类的方法缓存列表
2.如果上面的方法返回NO的话,对象会调用forwardingTargetForSelector方法
允许作者选择其他的对象,处理这个消息。
这个方法,也是待会我们要做文章的地方。画重点。
3.如果上面两个方法都没有做处理,那么对象会执行最后一个方法methodSignatureForSelector,提供一个有效的方法签名,若提供了有效的方法签名,程序将会通过forwardInvocation方法执行签名。若没有提供方法签名就会触发doesNotRecognizeSelector方法,触发崩溃。

整个调用流程图如下:

 整个代码调用顺序如下:

复制代码
//1+ (BOOL)resolveClassMethod:(SEL)sel {     NSLog(@"1---%@",NSStringFromSelector(sel));     NSLog(@"1---%@",NSStringFromSelector(_cmd));     return NO; } + (BOOL)resolveInstanceMethod:(SEL)sel {     NSLog(@"1---%@",NSStringFromSelector(sel));     NSLog(@"1---%@",NSStringFromSelector(_cmd));     return NO; } //2- (id)forwardingTargetForSelector:(SEL)aSelector {     NSLog(@"2---%@",NSStringFromSelector(aSelector));     NSLog(@"2---%@",NSStringFromSelector(_cmd));     return nil; } //3.最后一步,返回方法签名-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{     NSLog(@"3---%@",NSStringFromSelector(aSelector));     NSLog(@"3---%@",NSStringFromSelector(_cmd));     if ([NSStringFromSelector(aSelector) isEqualToString:@"gogogo"]) {         return [[UnknownModel2 new] methodSignatureForSelector:aSelector];     }     return [super methodSignatureForSelector:aSelector]; } //3.1处理返回的方法签名-(void)forwardInvocation:(NSInvocation *)anInvocation{     NSLog(@"4---%@",NSStringFromSelector(_cmd));     NSLog(@"4-最后一步--%@",anInvocation);     if ([NSStringFromSelector(anInvocation.selector) isEqualToString:@"gogogo"]) {         [anInvocation invokeWithTarget:[UnknownModel2 new]];     }else{         [super forwardInvocation:anInvocation];     } } //触发崩溃- (void)doesNotRecognizeSelector:(SEL)aSelector {      }
复制代码

打印结果如下:

复制代码
2018-12-27 00:
                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信