runtime动态添加方法引出的消息转发
来源:互联网 发布:php打印空格 编辑:程序博客网 时间:2024/05/18 19:35
首先甩出官方文档链接:
https://developer.apple.com/reference/objectivec/1418901-class_addmethod?language=objc
运行时开放的接口
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
- 一:四个参数的意义:
1:cls
添加类方法到哪个类上面去
2:name
一个选择器,用于指定方法的名称,即:方法的名称
3:imp
新方法的实现函数,这个函数必须至少有两个参数 self 和 _cmd (根据运行时官方文档的解释:An Objective-C method is simply a C function that take at least two arguments—self and _cmd. For example, given the following function: void myMethodIMP(id self, SEL _cmd)
{
// implementation ....
}
一个OC的方法,其实就是一个至少有self 和 _cmd两个参数的C函数)
4:types
一个字符的集合,用来描述这个方法的参数类型,其他可能的值,请参阅
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100其中第二个和第三个字符必须为”@:”.而第一个参数是要添加的函数的返回值类型.
- 二:返回值的意义
如果返回YES.则动态添加成功,如果是NO,则添加不成功(例如:当前类已经包含了一个同样名称方法的实现了);
- 三:按照苹果给出的动态添加类方法的例子如下
:
class_addMethod([self class], @selector(resolveThisMethodDynamically), (IMP) myMethodIMP, "v@:");
其中. resolveThisMethodDynamically就是在运行时.调用的当前类的并没有实现和声明的方法,而myMethodIMP就是一个C的函数,调用了resolveThisMethodDynamically方法后,执行的函数就是myMethodIMP
- 四:实例代码
为People动态添加一个方法
#import "People.h"#import <objc/runtime.h>int myMethodIMP(id self, SEL _cmd,NSString *str){ NSLog(@"动态添加的方法做的事 %@",str); return 100;}@implementation People+ (BOOL)resolveInstanceMethod:(SEL)sel{ SEL method = NSSelectorFromString(@"resolveThisMethodDynamically"); if (sel == method) { class_addMethod([self class], method, (IMP)myMethodIMP, "i@:"); return YES; } return [super resolveInstanceMethod:sel];}@end
在viewDidLoad里面调用
- (void)viewDidLoad { [super viewDidLoad]; People *P = [[People alloc]init]; [P performSelector:@selector(resolveThisMethodDynamically) withObject:@"lausen"];}
可以看到.上述方法中用到了+ (BOOL)resolveInstanceMethod:(SEL)sel这个方法,涉及到了OC中消息的转发.
- 五:消息的转发
OC中,对象调用方法是一个给对象发送消息的过程,因为OC采用的是”动态绑定机制”,要调用的方法,知道运行时才能确定。
如果对象不能接受这个消息,就会调用以下这几个方法,给你进行”消息转发”的机会,我们就是利用这几个方法进行消息转发,需要注意的是,按顺序执行以下方法,如果前面的已经实现了,并且执行了,就不会执行下面的方法。如果都没执行,那么程序就会报错
第一个:
+ (BOOL)resolveClassMethod:(SEL)sel + (BOOL)resolveInstanceMethod:(SEL)sel
第二个:
- (id)forwardingTargetForSelector:(SEL)aSelector
第三个:
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector- (void)forwardInvocation:(NSInvocation *)anInvocation
三个方法的调用顺序和前后关系,如下图所示,(盗图:http://blog.csdn.net/li198847/article/details/51375635)
第一个方法:如果返回YES.则表示可以处理消息,如果处理不了,则调用第二个方法(其实第一个方法,就是看一下如果当前的类/对象,处理不了这个消息,那就看一下,当前的类里面有没有通过运行时去动态添加方法,来进行消息转发)
第二个方法:通过该方法.返回一个可以处理该消息的对象,
例如:新建一个Animal类和Dog类,均继承自NSObject
在Animal类里面声明一个和Dog一样的一个方法
Animal.h
#import <Foundation/Foundation.h>@interface Animal : NSObject- (void)run:(NSString *)age;@end
Animal.m里面实现
#import "Animal.h"#import "Dog.h"@implementation Animal- (id)forwardingTargetForSelector:(SEL)aSelector{ NSString *selStr = NSStringFromSelector(aSelector); if ([selStr isEqualToString:@"run:"]) { return [[Dog alloc] init]; } return [super forwardingTargetForSelector:aSelector];}@end
Dog.h
#import <Foundation/Foundation.h>@interface Dog : NSObject- (void)run:(NSString *)age;@end
Dog.m
#import "Dog.h"@implementation Dog- (void)run:(NSString *)age{ NSLog(@"%@岁的��在跑",age);}@end
用Animal调用Animal的run方法
- (void)viewDidLoad { [super viewDidLoad]; Animal *animal = [[Animal alloc]init]; [animal run:@"2"];}
打印结果如下:
- runtime动态添加方法引出的消息转发
- Runtime(二)动态添加方法以及消息转发机制
- runtime之动态添加方法(动态决议,请求转发)
- runTime 的消息转发机制
- Runtime-动态添加方法
- runtime - 方法动态添加
- runtime - 动态添加方法
- Runtime的使用7 【动态添加方法】
- iOS开发------runtime之动态添加方法(动态决议,请求转发)
- Runtime消息机制,交换方法,动态添加方法,分类添加属性
- Runtime之消息转发
- iOS runtime 消息转发
- runtime基础、消息转发
- Runtime消息转发机制
- Runtime消息转发机制
- 【Runtime】动态添加方法demo
- iOS的动态创建实例方法和实现消息转发
- 动态方法决议 和 消息转发
- Kendo UI使用笔记
- 目前大数据最缺的是什么?
- Unity性能优化
- 全排列--非递归实现
- iOS中UIScrollView极限优化:两个UIImageView循环利用
- runtime动态添加方法引出的消息转发
- 图像特征提取三大法宝:HOG特征,LBP特征,Haar特征
- 388. Longest Absolute File Path
- 【Java】UML类图几种关系的总结
- Linux 五种 IO模型 性能分析
- Map四种方法的读写性能对比
- html5新增的标签
- 如何打造一款直播App(方法流程)
- CUDA Intro - Variable block.x and blockIdx.x