iOS 之runtime消息传递和转发

2022-02-18  本文已影响0人  男人宫
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

上一篇 下一篇

猜你喜欢

热点阅读