先介绍下class_addMethod这个fangfa

  1.  
    /**
  2.  
    * Adds a new method to a class with a given name and implementation.
  3.  
    *
  4.  
    * @param cls The class to which to add a method.
  5.  
    * @param name A selector that specifies the name of the method being added.
  6.  
    * @param imp A function which is the implementation of the new method. The function must take at least two arguments—self and _cmd.
  7.  
    * @param types An array of characters that describe the types of the arguments to the method.
  8.  
    *
  9.  
    * @return YES if the method was added successfully, otherwise NO
  10.  
    * (for example, the class already contains a method implementation with that name).
  11.  
    *
  12.  
    * @note class_addMethod will add an override of a superclass's implementation,
  13.  
    * but will not replace an existing implementation in this class.
  14.  
    * To change an existing implementation, use method_setImplementation.
  15.  
    */
  16.  
    OBJC_EXPORT BOOL class_addMethod(Class cls, SEL name, IMP imp,
  17.  
    const char *types)
  18.  
    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

动态决议方法:

  1.  
    + (BOOL)resolveClassMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
  2.  
    + (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类

  1.  
    #import "Person.h"
  2.  
    #import <objc/runtime.h>
  3.  
     
  4.  
    @implementation Person
  5.  
     
  6.  
     
  7.  
    + (BOOL)resolveInstanceMethod:(SEL)sel {
  8.  
    Method exchangeM = class_getInstanceMethod([self class], @selector(eatWithPersonName:));
  9.  
    class_addMethod([self class], sel, class_getMethodImplementation(self, @selector(eatWithPersonName:)),method_getTypeEncoding(exchangeM));
  10.  
    return YES;
  11.  
    }
  12.  
     
  13.  
    - (void)eatWithPersonName:(NSString *)name {
  14.  
    NSLog(@"Person %@ start eat ",name);
  15.  
    }
  16.  
     
  17.  
     
  18.  
     
  19.  
    @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

然后测试

  1.  
    Person *person = [[Person alloc]init];
  2.  
    //调用Person未实现方法eat
  3.  
    [person performSelector:@selector(eat) withObject:@"minzhe"];

运行结果:

2017-07-14 14:41:35.297 RunTimeAddMethod[1458:379458] Person minzhe start eat 

好了   添加上了    这样就没有 crash

最新文章

  1. HTML5的postMessage使用记要
  2. Chrome开发工具Elements面板(编辑DOM和CSS样式)详解
  3. LUA闭包概念演示
  4. Android拍照、录像、录音代码范例
  5. 【BZOJ】【1202】【HNOI2005】狡猾的商人
  6. 教程:30分钟学会Adobe Premiere
  7. 窗口绘制有关的消息整理 WM_PAINT, WM_NCPAINT, WM_ERASEBKGND
  8. Android Dalvikvm 内存管理理解
  9. readelf -s 命令‘symbol’名字显示不全
  10. Ubuntu环境变量——系统变量和用户变量
  11. Hibernate基础知识总结
  12. 关于用VMware克隆linux系统后,无法联网找不到eth0网卡的问题
  13. 高仿QQ头像截取
  14. mac上php版本切换
  15. 【bfs】最少转弯问题
  16. Css新增内容
  17. bitnami_redmine3.3.0-1 问题及备份恢复
  18. Avoiding Common Networking Mistakes
  19. 字典取KEY,占位符,延迟刷新
  20. Hadoop生态圈-phoenix的视图(view)管理

热门文章

  1. pip国内镜像永久
  2. 12组-Beta冲刺-1/5
  3. Task :app:lintVitalRelease FAILED
  4. java中带回调函数的字符串替换,类似js中的replace(rgExp,function)
  5. py正则与re模块
  6. make编译工具教程
  7. ELKF搭建
  8. JS实现打字效果(_会闪烁)
  9. win的安全更新安装不成功,可用下面命令进行强制更新
  10. AutoMapper在.Net Core WebApi中使用