工作中没怎么用到runtime的东西,所以一直没怎么看,现在开始拿起来。

runtime之方法的交换:

都知道OC中有category可以对已知类进行扩展,但是假如工程中需要修改某类的原方法,若用category的话,调用的时候会调用到category中实现的方法,而原方法中的功能就已经被覆盖,这样就调用不到系统的方法了,为了避免这种情况,我们可以用方法交换的形式:
如写一个NSURL的分类,现在将它的URLWithString:的方法替换成我们自己写的方法:

+ (void)load{
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    Method urlWithStringMethod = class_getClassMethod(self, @selector(URLWithString:));

    Method wd_urlWithStringMethod = class_getClassMethod(self, @selector(WD_urlWithString:));

    /*交换了URLWithString和WD_urlWithString的函数指针(该指针指向方法的实现),所以交换了之后,若调用URLWithString:方法,实际上是调用了WD_urlWithString方法的实现,而调用了WD_urlWithString:方法,实际上的调用了URLWithString:方法的实现*/

    method_exchangeImplementations(urlWithStringMethod, wd_urlWithStringMethod);
  });
}

/*
在load中将NSURL中的URLWithString方法跟自定义的WD_urlWithString进行了交换
在外部调用系统的URLWithString:方法,实际上会到WD_urlWithString:中
*/
+ (instancetype)WD_urlWithString:(NSString *)urlString{
  NSURL *url = [NSURL WD_urlWithString:urlString]; //实际调用的URLWithString:方法的实现,所以不会造成无限循环
  if (url == nil) {
    NSLog(@"url is null");
  }
  return url;
}

method:

实际上method是一个结构体,

struct objc_method {
  SEL method_name OBJC2_UNAVAILABLE;
  char *method_types OBJC2_UNAVAILABLE;
  IMP method_imp OBJC2_UNAVAILABLE;
}

method_name 是方法的 selector,可以理解为运行时的方法名;
*method_types 是一个参数和返回值类型编码的字符串;
method_imp 是指向方法实现的指针。
Method Swizzling 的实质是在运行时,访问对象的方法结构体,并改变它的底层实现。

拿上面的例子来说,变化如下:

交换前->

method URLWithString {
  SEL method_name = @selector(URLWithString:)
  char *method_types = “v@:“ //返回值void, 参数id(self),selector(_cmd)
  IMP method_imp = 0x000FFFF //指向([NSURL URLWithString:])
}
method WD_urlWithString {
  SEL method_name = @selector(WD_urlWithString:)
  char *method_types = “v@:“ //返回值void, 参数id(self),selector(_cmd)
  IMP method_imp = 0x000EEEE //指向([NSURL WD_urlWithString:])
}
交换后->
method URLWithString {
  SEL method_name = @selector(URLWithString:)
  char *method_types = “v@:“ //返回值void, 参数id(self),selector(_cmd)
  IMP method_imp = 0x000FFFF //指向([NSURL WD_urlWithString:])
}
method WD_urlWithString {
  SEL method_name = @selector(WD_urlWithString:)
  char *method_types = “v@:“ //返回值void, 参数id(self),selector(_cmd)
  IMP method_imp = 0x000EEEE //指向([NSURL URLWithString:])
}
可以看到使用method_exchangeImplementations实质是交换它们的IMP。
Method Swizzling,我们可以对系统中的方法进行修改,动态添加。

在load中处理,因为 +load 方法会在类被添加到 OC 运行时执行,保证了 Swizzling 方法的及时处理。

runtime之方法的交换的更多相关文章

  1. ios - runtime运行时应用---交换方法

    runtime运行时用法之一 --- 交换类的方法,此处简单写了把系统的UIView的setBackgroundColor的方法换成了自定义的pb_setBackgroundColor 首先创建UIV ...

  2. Runtime之方法

    前两篇介绍了类与对象.成员变量&属性&关联对象的相关知识,本篇我们将开始讲解Runtime中最有意思的一部分内容:消息处理机制.我们从一个示例开始. 在OC中,我们使用下面这种方式来调 ...

  3. Java Runtime.availableProcessors()方法

    Java Runtime.availableProcessors()方法用法实例教程.   描述 java.lang.Runtime.availableProcessors() 方法返回到Java虚拟 ...

  4. Linux系统实现虚拟内存有两种方法:交换分区(swap分区)和交换文件

    Linux系统实现虚拟内存有两种方法:交换分区(swap分区)和交换文件 交换文件 查看内存:free -m , -m是显示单位为MB,-g单位GB 创建一个文件:touch /root/swapfi ...

  5. Mac下 eclipse target runtime com.genuitec.runtime 解决方法

    Mac下 eclipse target runtime com.genuitec.runtime 解决方法 解决步骤如下: 首先是找到工程项目一个名叫.settings的文件夹,里面有个叫 org.e ...

  6. runtime 实现方法交换 viewwillappear方法

    1.新建分类 #import "UIViewController+swizzling.h"#import <objc/runtime.h> @implementatio ...

  7. Runtime之方法交换

    在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写.和借助类别重名方法暴力抢先之外,还有就是方法交换 方法交换的原理:在OC中调用一个方法其实是向一个对象发送消息,查找消息的唯一 ...

  8. [runtime] initialize方法讲解

    + (void)initializeDescription(描述)    Initializes the class before it receives its first message. 在这个 ...

  9. Objective-C 方法交换实践(二) - 方法指针交换

    一. 基本函数 根据 sel 得到 class 的实例方法 Method class_getInstanceMethod(Class cls, SEL name) 根据 sel 得到 class 的函 ...

随机推荐

  1. Codeforces Gym 100733I The Cool Monkeys 拆点+最大流

    原题链接:http://codeforces.com/gym/100733/problem/I 题意 有两颗树(只是树,不是数据结构),每棵树上有不同高度的树枝,然后有m只猴子在某棵树的前m高的树枝上 ...

  2. 调用tf.softmax_cross_entropy_with_logits函数出错解决

    原来这个函数,不能按以前的方式进行调用了,只能使用命名参数的方式来调用.原来是这样的: tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y ...

  3. win7 32位配置apache+wsgi+django环境

    1下载xampp,里面有apache,mysql,phpmyadmin, 2 下载wsgi,http://download.csdn.net/download/copter/9192361 将对应的模 ...

  4. django忘记超级用户密码的解决方法

    用Django shell: 1 python manage.py shell 然后获取你的用户名,并且重设密码: 1 2 3 4 from django.contrib.auth.models im ...

  5. Samp免流软件以及地铁跑酷的自校验分析

    [文章标题]:Samp免流软件以及地铁跑酷的自校验分析 [文章作者]: Ericky [作者博客]: http://blog.csdn.net/hk9259 [下载地址]: 自行百度 [保护方式]: ...

  6. 百度地图之标注一组地理坐标&lt;2&gt;

    一.需求 开发移动地图相关的应用有时会有这种需求:在地图上显示自己的定位,然后想查看周边使用这个应用的有哪些人.当然完毕这个功能须要后台数据的支持.你要把自己的位置信息发给后台,后台在依据你的位置查询 ...

  7. Sencha touch 初体验

    一.什么是Sencha Touch? Sencha Touch是一个应用手持移动设备的前端js框架,与extjs是同一个门派的,它继承了extjs的优点和缺点.功能很强大,效果很炫丽,效率不高. 二. ...

  8. mycat 连续分片 -&gt; 按日期(天)分片

    1,按日期(天)分片 按日期(天)分片:从開始日期算起,依照天数来分片 比如,从2016-01-01.每10天一个分片 注意事项:须要提前将分片规划好,建好.否则有可能日期超出实际配置分片数 2,加入 ...

  9. Windows下利用CMake和VS2013编译OpenCV

    转载自:http://www.chengxulvtu.com/2014/03/19/windows_build-opencv-with-cmake-and-vs2013.html   获取OpenCV ...

  10. Codeforces Round #243 (Div. 1)——Sereja and Squares

    题目链接 题意: 给n个点,求能组成的正方形的个数. 四边均平行与坐标轴 大神的分析: 经典题 我们考虑每一种x坐标,显然仅仅有<= sqrt{N}个x坐标出现了> sqrt{N}次,我们 ...