iOS用runtime给一个类动态添加方法 ---class_addMethod
先介绍下class_addMethod这个fangfa
- /**
- * Adds a new method to a class with a given name and implementation.
- *
- * @param cls The class to which to add a method.
- * @param name A selector that specifies the name of the method being added.
- * @param imp A function which is the implementation of the new method. The function must take at least two arguments—self and _cmd.
- * @param types An array of characters that describe the types of the arguments to the method.
- *
- * @return YES if the method was added successfully, otherwise NO
- * (for example, the class already contains a method implementation with that name).
- *
- * @note class_addMethod will add an override of a superclass's implementation,
- * but will not replace an existing implementation in this class.
- * To change an existing implementation, use method_setImplementation.
- */
- OBJC_EXPORT BOOL class_addMethod(Class cls, SEL name, IMP imp,
- const char *types)
- OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
这是文档
描述就是:给一个类添加一个新的方法和该方法的具体实现
参数:
第一个
Class cls
cls :你要添加新方法的那个类
第二个
SEL name
name :要添加的方法
第三个
IMP imp
imp:指向实现方法的指针 就是要添加的方法的实现部分
第四个
const char *types
*types:我们要添加的方法的返回值和参数 叫 type encodings 这个东西怎么写我就不说了 可以去查 在这里我有一个懒办法得到它不用暴力手打 往后看
然后这个方法的描述和参数说完了,下面说说他用在哪,
给一个类用运行时添加一个方法 他可以用来解决我们开发中的这个问题------“unrecognized selector sent to instance 0x7faa2a132c0”
在OC中我们调用一个方法时 有个关键字 叫 “消息机制” 就是执行 [receiver message]; 这句代码其实就是发送了一个消息 (发消息的详细过程我就不写了 感兴趣 去查),
消息里面带着你调用这个方法的名称和参数以及是哪个对象发送的消息,然后 发出消息后 如果有对应的方法响应,就执行方法,没有的话就报“unrecognized selector sent to instance 0x7faa2a132c0” ,然后就crash ,为了防止crash我们可以用class_addMethod给找不到对应方法即将crash的消息添加一个与之对应的方法来防止其因为找不到相应方法而crash
在OC中找不到对相应的实现方法时 有补救机制 即 会先调用动态决议方法 该方法解决不了问题 再调用重定向方法 都解决不了问题是 crash
动态决议方法:
- + (BOOL)resolveClassMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
- + (BOOL)resolveInstanceMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
重定向方法:
- (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
下面上代码:给一个类的对象调用一个未实现的方法 然后用runtime 在动态决议方法中为其添加实现 防止crash
Person类
- #import "Person.h"
- #import <objc/runtime.h>
- @implementation Person
- + (BOOL)resolveInstanceMethod:(SEL)sel {
- Method exchangeM = class_getInstanceMethod([self class], @selector(eatWithPersonName:));
- class_addMethod([self class], sel, class_getMethodImplementation(self, @selector(eatWithPersonName:)),method_getTypeEncoding(exchangeM));
- return YES;
- }
- - (void)eatWithPersonName:(NSString *)name {
- NSLog(@"Person %@ start eat ",name);
- }
- @end
里面重写resolveInstanceMethod方法 给找不到实现的方法 添加实现 - (void)eatWithPersonName:(NSString *)name;
第一句
Method exchangeM = class_getInstanceMethod([self class], @selector(eatWithPersonName:));
是为下面method_getTypeEncoding(exchangeM) 做铺垫 这样就拿到了eatWithPersonName方法的type encodings 用作class_addMethod的第四个参数,就是上面我提到的不用暴力手打的获取type encodings的方法
然后调用 class_addMethod 为当前类[self class] 的sel 方法 添加实现 class_getMethodImplementation(self, @selector(eatWithPersonName:)) 这一串就是拿到方法eatWithPersonName的IMP指针 然后最后一个参数是 type encodings
然后测试
- Person *person = [[Person alloc]init];
- //调用Person未实现方法eat
- [person performSelector:@selector(eat) withObject:@"minzhe"];
运行结果:
2017-07-14 14:41:35.297 RunTimeAddMethod[1458:379458] Person minzhe start eat
好了 添加上了 这样就没有 crash
iOS用runtime给一个类动态添加方法 ---class_addMethod的更多相关文章
- ios开发runtime学习三:动态添加方法(实际应用少,面试)
#import "ViewController.h" #import "Person.h" /* 1: Runtime(动态添加方法):OC都是懒加载机制,只要 ...
- 使用runtime给类动态添加方法并调用 - class_addMethod
上手开发 iOS 一段时间后,我发现并不能只着眼于完成需求,利用闲暇之余多研究其他的开发技巧,才能在有限时间内提升自己水平.当然,“其他开发技巧”这个命题对于任何一个开发领域都感觉不找边际,而对于我来 ...
- ios开发runtime学习四:动态添加属性
#import "ViewController.h" #import "Person.h" #import "NSObject+Property.h& ...
- 给python类动态添加方法(method)
群里有人问如何做到 def foo(): pass class Bar(object): pass Bar.set_instance_method(foo) b = Bar() b.foo() 这个其 ...
- ios的runtime为什么可以动态添加方法
一句话概括 每个instance都有一个isa,这个isa,里面含有所有的方法列表,ios提供库函数增加,修改,即实现了动态添加方法
- 使用TypeDescriptor给类动态添加Attribute
给类动态添加Attribute一直是我想要解决的问题,从msdn里找了很久,到Stack Overflow看了不少文章,算是最终有了答案. 先是有这样的一段解释 Attributes are stat ...
- iOS运行时使用(动态添加方法)
1 举例 我们实现一个Person类 然后Person 其实是没得对象方法eat:的 下面调用person的eat方法 程序是会奔溃的 那么需要借助运行时动态的添加方法 Person *p = [[ ...
- python装饰器、继承、元类、mixin,四种給类动态添加类属性和方法的方式(一)
介绍装饰器.继承.元类.mixin,四种給类动态添加类属性和方法的方式 有时候需要給类添加额外的东西,有些东西很频繁,每个类都需要,如果不想反复的复制粘贴到每个类,可以动态添加. # coding=u ...
- 快速上手Runtime(四)之动态添加方法
如果一个类方法非常多,加载类到内存的时候也比较耗费资源,可以使用动态给某个类,添加方法解决.做到优化内存,节省资源的效果. // // Person.m // ResolveInstanceMetho ...
- php里面用魔术方法和匿名函数闭包函数动态的给类里面添加方法
1.认识 __set (在给不可访问属性赋值时,__set() 会被调用) 也就是说你再访问一个类里面没有的属性,会出发这个方法 class A{ private $aa = '11'; publ ...
随机推荐
- solve--ifconifg命令提示没有该命令解决方法
一.如果你/bin目录下有ifconfig,则是命令路径没有在环境变量中添加,很多新装的linux系统都会存在这种问题 打开/etc/profile文件 命令: vi /et ...
- Python学习笔记(三)数据类型转换
一.输入输出函数 1.input() 输入函数,内置函数,用来获取用户输入数据,返回值为字符串 运行到此函数会阻塞或暂停程序 示例: 1 str_data = input('请输入数据:') 2 st ...
- 关于新手在使用git过程中的基本问题--前端开发篇
1.首先git是什么? git学名叫做分布式版本控制系统. 它能做啥呢?想一想,你在写项目的时候,尤其是大型的协作项目,往往一个项目会经过很多次修改才上线,在这个过程中,你会写项目1.0版.2.0版诸 ...
- JQuery的dataTable实现分页
关于dataTable基本使用有很多帖子说的很详细,在此不做详述. 最近使用dataTable处理服务器返回分页数据时遇到问题,问题解决后有一些心得分享一下: 1. 如果打开界面通过dataTable ...
- JVM中类加载子系统
1.类加载子系统中有哪些常用类加载器? 1.BootStrapClassLoader(负责加载基础类库中的类,例如Object,String....) 2.ExtClassLoader(负责加载扩展类 ...
- py正则与re模块
正则表达式符号介绍 按照博客中的表格罗列的去记即可 了解 \w,\s,\d与\W,\S,\D相反的匹配关系(对应的两者结合就是匹配全局) \t匹配制表符 \b匹配结尾的指定单词 优先掌握 ^:以什么什 ...
- 第13周 预习、实验与作业:Java网络编程
编写一个网络程序,为了与其他网络程序通信,至少要知道对方的什么信息? IP地址 TCP与UDP协议有什么不同的呢?什么时候该选择哪种协议?HTTP使用的是TCP还是UDP?不重要的短信息传送之类的功能 ...
- 《Python深度学习》《卷积神经网络的可视化》精读
对于大多数深度学习模型,模型学到的表示都难以用人类可以理解的方式提取和呈现.但对于卷积神经网络来说,我们可以很容易第提取模型学习到的表示形式,并以此加深对卷积神经网络模型运作原理的理解. 这篇文章的内 ...
- 取消Andorid设备的严格模式
在做文件拍照选择等应用时,发现7.0以上手机需要主动关闭严格模式才能让代码不报错 通过关闭严格模式绕过fileprovider 权限的控制的方法,绕过FileProvider在应用间共享文件的限制 7 ...
- Windows支持多个远程连接
1.点击 开始-->运行-->输入"gpedit.msc",进入本地组策略编辑器 2.点击 计算机配置-->管理模板-->Windows组件-->远程 ...