iOS开发------runtime之动态添加方法(动态决议,请求转发)
来源:互联网 发布:世界卫生组织官网数据 编辑:程序博客网 时间:2024/05/17 18:19
RunTime中实例变量调用方法的步骤:
1、在该实例变量的方法缓存列表中查找方法,如果找到执行.
2、如果没找到,会去类结构中的相应方法列表中进行查找,如果找到执行.
3、如果方法列表没有找到该方法,那么就从父类中进行1、2部操作.
4、如果直到根类仍然没有找到方法,那么就会报错:unrecognized selector sent to instance 0x1005046c0.
也就是说
1、重写父类的方法,本质上不是覆盖了父类的方法,只不过是在本类中找到相应的方法,不再去父类中查找方法而已
2、super关键字并不是指父类,作用是 跳过此类直接从父类中进行查找方法
动态决议以及请求转发就是拦截上述过程,让其在runtime中运行相应的方法
动态决议
实现下面的两个方法
//对类对象进行决议+ (BOOL)resolveClassMethod:(SEL)sel __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);//对实例对象进行决议+ (BOOL)resolveInstanceMethod:(SEL)sel __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
返回值以及参数:
返回值:表示动态决议的成功与否
参数:sel 需要进行动态决议的方法
添加方法
/** * 运行时添加方法的函数 * * @param cls 需要动态决议的类 * @param name 需要动态决议的方法 * @param imp 需要执行方法的指针(本人理解为函数指针) * @param types 类型字符串,后面详细说 * * @return 添加的结果 */(BOOL)class_addMethod(Class cls,SEL name,IMP imp,const char * types)
用代码来实现,更加简明,建立一个测试类RunTimeClass1:NSObject,不实现任何的方法:
在main中实现下面方法
RunTimeTextClass1 * class1 = [[RunTimeTextClass1 alloc]init];[class1 performSelector:@selector(Text1) withObject:@"哈哈哈哈"];
因为类中根本没有这个方法,所以结果相信也都知道crash了,因为找不到这个方法的内存地址
RunTime[1047:62333] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[RunTimeTextClass1 Text1]: unrecognized selector sent to instance 0x100107540'
那么在RunTimeClass1中实现下面方法,需要导入头文件:<objc/runtime.h>
//实例变量的动态决议,类方法的动态决议是一样的+(BOOL)resolveInstanceMethod:(SEL)sel{ if ([NSStringFromSelector(sel) isEqualToString:@"Text1"]) { NSLog(@"RunTimeTextClass1 实例对象动态决议!"); class_addMethod([self class], sel, (IMP)test1, "v@:@"); } return [super resolveInstanceMethod:sel];}
实现决议的方法test1,楼主使用C实现的,如果是用Objc实现的,可以通过方法:+(IMP)instanceMethodForSelector:(SEL)aSelector来转换,Objc的方法是至少有id self,SEL _cmd两个参数的普通C语言的函数,必须要有这两个参数
void test1(id self,SEL _cmd,NSString *str){ NSLog(@"%@",str);}
再来解释一下types这个字符串:
v :表示函数的返回值void
@:表示参数id self
: :表示SEL对象
@:表示后面的参数str:NSString
下面是苹果官方规定的符号:
接下来在运行一下,结果就不报错了,并执行了我们决议后的方法
请求转发
实现下面两个方法
//调用不存在的方法的时候重定向到一个有该方法的对象- (id)forwardingTargetForSelector:(SEL)aSelector __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);//将调用不存在的方法封装成NSInvocation对象传出,做完处理调用invokeWithTarget:方法触发- (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE("");
在RunTimeTextClass1中调用-text1方法,但是在.h与.m中都没有实现这个方法,也不给他实现动态决议方法,调用方法text1
RunTimeTextClass1 * class1 = [[RunTimeTextClass1 alloc]init];[class1 performSelector:@selector(text1)];
实现-forwardingTargetForSelector:方法来完成请求转发
然后在RunTimeTextClass1中实现第一个方法:-(id)forwardingTargetForSelector:(SEL)aSelector{ return [[Text alloc]init];}
//// Text.m// RunTime//// Created by YueWen on 16/2/24.// Copyright © 2016年 YueWen. All rights reserved.//#import "Text.h"@implementation Text-(void)text1{ NSLog(@"我是Text!");}@end
实现forwardingInvocation:方法来完成请求转发
首先实现这个方法:
-(void)forwardInvocation:(NSInvocation *)anInvocation{ Text * text = [[Text alloc]init]; SEL selector = anInvocation.selector; if ([text respondsToSelector:selector])//如果有这个方法 { [anInvocation invokeWithTarget:text];//触发方法 } else { [super forwardInvocation:anInvocation]; }}
但是用上面的方法来实现,还需要实现一个方法,为这个类对象进行方法签名:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{ return [Text instanceMethodSignatureForSelector:aSelector];}
这样再来看看效果,和上面的效果是一样的:
如果动态决议和请求转发都实现了,那么动态决议的优先级要高于请求转发.
0 0
- iOS开发------runtime之动态添加方法(动态决议,请求转发)
- runtime之动态添加方法(动态决议,请求转发)
- IOS动态方法决议
- 动态方法决议 和 消息转发
- cocoa动态方法决议及消息转发
- 动态方法决议与消息转发
- runtime系列3--Dynamic Method Resolution-方法的动态决议
- Runtime(二)动态添加方法以及消息转发机制
- runtime动态添加方法引出的消息转发
- ios runtime 动态向类添加方法
- Runtime-动态添加方法
- runtime - 方法动态添加
- runtime - 动态添加方法
- 【Runtime】动态添加方法demo
- Objective-C运行时编程指南之动态方法决议
- iOS开发------runtime关联对象(动态添加属性)
- iOS用runtime给一个类动态添加方法 ---class_addMethod
- iOS开发之category动态添加属性的方法------关联
- IOS开发中的微信支付功能
- 导入Excel至SQL Server
- jQuery学习笔记二(jQuery语法)
- 关于Comparable接口
- 三天学会HTML5 ——多媒体元素的使用
- iOS开发------runtime之动态添加方法(动态决议,请求转发)
- DELL一体机无法开机解决办法
- cocos 手游开发与 cocos-html5 页游的屏幕适配
- Android线程和线程池(一)--AsyncTask
- android中TextView嵌套在ScrollView中并自由滚动
- 解决Android手机修改hosts不起作用的问题
- Hibernate ORM入门04
- 国内外开源镜像地址(持续更新)
- lasrevarTredrotsoPdnaredronImorfeerTyraniBtcurtsnoC.106