runtime选择器和消息转发处理

来源:互联网 发布:魔法王座 知乎 编辑:程序博客网 时间:2024/05/21 16:21

方法相关的操作函数

// 调用指定方法的实现id method_invoke ( id receiver, Method m, ... );// 调用返回一个数据结构的方法的实现void method_invoke_stret ( id receiver, Method m, ... );// 获取方法名SEL method_getName ( Method m );// 返回方法的实现IMP method_getImplementation ( Method m );// 获取描述方法参数和返回值类型的字符串const char * method_getTypeEncoding ( Method m );// 获取方法的返回值类型的字符串char * method_copyReturnType ( Method m );// 获取方法的指定位置参数的类型字符串char * method_copyArgumentType ( Method m, unsigned int index );// 通过引用返回方法的返回值类型字符串void method_getReturnType ( Method m, char *dst, size_t dst_len );// 返回方法的参数的个数unsigned int method_getNumberOfArguments ( Method m );// 通过引用返回方法指定位置参数的类型字符串void method_getArgumentType ( Method m, unsigned int index, char *dst, size_t dst_len );// 返回指定方法的方法描述结构体struct objc_method_description * method_getDescription ( Method m );// 设置方法的实现IMP method_setImplementation ( Method m, IMP imp );// 交换两个方法的实现void method_exchangeImplementations ( Method m1, Method m2 );

方法选择器函数

// 返回给定选择器指定的方法的名称const char * sel_getName ( SEL sel );// 在Objective-C Runtime系统中注册一个方法,将方法名映射到一个选择器,并返回这个选择器SEL sel_registerName ( const char *str );// 在Objective-C Runtime系统中注册一个方法SEL sel_getUid ( const char *str );// 比较两个选择器BOOL sel_isEqual ( SEL lhs, SEL rhs );

消息转发

////  MethodTool.h//  RunTimeExample////  Created by kobe on 16/2/25.//  Copyright (c) 2016年 kobe. All rights reserved.//#import <Foundation/Foundation.h>@interface MethodTool : NSObject-(void)method2;@end
////  MethodTool.m//  RunTimeExample////  Created by kobe on 16/2/25.//  Copyright (c) 2016年 kobe. All rights reserved.//#import "MethodTool.h"@interface MethodTool()@end@implementation MethodTool-(void)method2{    NSLog(@"消息工具处理中");     NSLog(@"%@, %p", self, _cmd);}@end

首先执行的是动态方法解析

////  RuntimeMethod.m//  RunTimeExample////  Created by kobe on 16/2/25.//  Copyright (c) 2016年 kobe. All rights reserved.//#import "RuntimeMethod.h"#import "MethodTool.h"#import <objc/runtime.h>@interface RuntimeMethod(){    MethodTool *methodTool;}@end@implementation RuntimeMethod+(instancetype)object{    return [[self alloc]init];}-(instancetype)init{    self=[super init];    if (self!=nil) {        methodTool=[[MethodTool alloc]init];    }    return self;}-(void)sendMessageOne{    [self performSelector:@selector(method2)];}//转发消息的方法void sendMessage(id self, SEL _cmd){    NSLog(@"动态解析方法处理完成");    //NSLog(@"%@,%p",self,_cmd);}//动态方法解析,对象在接受到未知消息的时候,首先调用这个方法(类的实例方法)+(BOOL)resolveInstanceMethod:(SEL)sel{    NSLog(@"动态解析方法");    //获取SEL    NSString *selectorString=NSStringFromSelector(sel);    if ([selectorString isEqualToString:@"method9"]) {        //为当前类添加一个消息转发的方法        class_addMethod(self.class, @selector(sendMessageOne), (IMP)sendMessage,"v@:");    }    return [super resolveInstanceMethod:sel];}@end

如果动态解析方法没处理,就执行备用消息处理
//备用消息接受

-(id)forwardingTargetForSelector:(SEL)aSelector{    NSLog(@"备用消息接受者");    NSString *selectorString = NSStringFromSelector(aSelector);    if ([selectorString isEqualToString:@"method9"]) {        return methodTool;    }    return [super forwardingTargetForSelector:aSelector];}

如果备用消息没处理就执行完整消息处理

//方法签名-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{    NSMethodSignature *signature=[super methodSignatureForSelector:aSelector];    if (!signature) {        if ([MethodTool instancesRespondToSelector:aSelector]) {            signature=[MethodTool instanceMethodSignatureForSelector:aSelector];        }    }    return signature;}//完整消息的转发-(void)forwardInvocation:(NSInvocation *)anInvocation{    NSLog(@"完整消息转发");    if ([MethodTool instancesRespondToSelector:anInvocation.selector]) {        [anInvocation invokeWithTarget:methodTool];    }}

使用方法

- (void)viewDidLoad {    [super viewDidLoad];    //消息转发处理    RuntimeMethod *runtimeMethod=[[RuntimeMethod alloc]init];    [runtimeMethod performSelector:@selector(sendMessageOne)];}

以上所有的方法名称必须是类里面拥有的,不然这些转发的消息处理函数就会报错

0 0