runtime 运行时,oc是一门动态性语言,程序在运行时可改变结构,如添加方法,交换方法等.其实runtime就是一组用c语言写的api
消息转发流程如下:
先调用实例方法resolveInstanceMethod
如果在这里使用runtime动态添加对应的方法,并且返回yes。就万事大吉。对象找到了处理的方法,
并且将这个新增的方法添加到类的方法缓存列表
如果上面的方法返回NO的话,对象会调用forwardingTargetForSelector方法
允许作者选择其他的对象,处理这个消息。
这个方法,也是待会我们要做文章的地方。画重点。
如果上面两个方法都没有做处理,那么对象会执行最后一个方法methodSignatureForSelector,提供一个有效的方法签名,若提供了有效的方法签名,程序将会通过forwardInvocation方法执行签名。若没有提供方法签名就会触发doesNotRecognizeSelector方法,触发崩溃。
Person *p = [Person new];
//调用一个未实现的实例方法
[p test];
//调用一个未实现的类方法
[Person test1];
//如果调用一个没有实现的方法,且没有动态解析,就会进行消息转发
[p study];
-------------------------------------------
//person类
#import "Person.h"
#import <objc/runtime.h>
#import "Man.h"
@implementation Person
//调用实例方法时未实现的话就会用此方法进行动态解析
+(BOOL)resolveInstanceMethod:(SEL)sel
{
//runtime动态添加方法
//v是返回值为void @:为固定格式 后面如果要参数跟对应的参数类型
class_addMethod(self.class, sel, class_getMethodImplementation(self.class, @selector(newMethods)), "v@:");
return YES;
}
- (void)newMethods
{
NSLog(@"我是动态添加的方法");
}
//调用类方法时未实现的话就会用此方法进行动态解析
+ (BOOL)resolveClassMethod:(SEL)sel
{
//runtime动态添加方法
//类方法存在元类中 所以要获取元类 给元类添加方法 objc_getMetaClass获取元类
class_addMethod(objc_getMetaClass("Person"), sel, class_getMethodImplementation(self.class, @selector(newClassMetods)), "v@:");
return YES;
}
- (void)newClassMetods
{
NSLog(@"我是动态添加的");
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
//指定一个对象来响应没有实现的方法
return [Man new];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
[anInvocation invokeWithTarget:[Man new]];
}
@end
-----------------------------------------------
//Man类
#import "Man.h"
@implementation Man
- (void)study
{
NSLog(@"我帮人类响应了这个方法");
}
@end
网友评论