runtime之方法的交换
工作中没怎么用到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之方法的交换的更多相关文章
- ios - runtime运行时应用---交换方法
runtime运行时用法之一 --- 交换类的方法,此处简单写了把系统的UIView的setBackgroundColor的方法换成了自定义的pb_setBackgroundColor 首先创建UIV ...
- Runtime之方法
前两篇介绍了类与对象.成员变量&属性&关联对象的相关知识,本篇我们将开始讲解Runtime中最有意思的一部分内容:消息处理机制.我们从一个示例开始. 在OC中,我们使用下面这种方式来调 ...
- Java Runtime.availableProcessors()方法
Java Runtime.availableProcessors()方法用法实例教程. 描述 java.lang.Runtime.availableProcessors() 方法返回到Java虚拟 ...
- Linux系统实现虚拟内存有两种方法:交换分区(swap分区)和交换文件
Linux系统实现虚拟内存有两种方法:交换分区(swap分区)和交换文件 交换文件 查看内存:free -m , -m是显示单位为MB,-g单位GB 创建一个文件:touch /root/swapfi ...
- Mac下 eclipse target runtime com.genuitec.runtime 解决方法
Mac下 eclipse target runtime com.genuitec.runtime 解决方法 解决步骤如下: 首先是找到工程项目一个名叫.settings的文件夹,里面有个叫 org.e ...
- runtime 实现方法交换 viewwillappear方法
1.新建分类 #import "UIViewController+swizzling.h"#import <objc/runtime.h> @implementatio ...
- Runtime之方法交换
在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写.和借助类别重名方法暴力抢先之外,还有就是方法交换 方法交换的原理:在OC中调用一个方法其实是向一个对象发送消息,查找消息的唯一 ...
- [runtime] initialize方法讲解
+ (void)initializeDescription(描述) Initializes the class before it receives its first message. 在这个 ...
- Objective-C 方法交换实践(二) - 方法指针交换
一. 基本函数 根据 sel 得到 class 的实例方法 Method class_getInstanceMethod(Class cls, SEL name) 根据 sel 得到 class 的函 ...
随机推荐
- gitignore 规则
在使用git的过程中,总有一些我们不想被跟踪的文件,例如vim的交换文件,编译产生的文件等等.这时,我们可以在项目的根目录下创建一个名为 .gitignore 的文件,列出不想被跟踪的文件模式即可.下 ...
- [Algorithms] Sort an Array with a Nested for Loop using Insertion Sort in JavaScript
nsertion sort is another sorting algorithm that closely resembles how we might sort items in the phy ...
- Python学习笔记8:标准库之正則表達式
Python拥有强大的标准库.从如今起,開始学习标准库中提供的一些经常使用功能. 首先看正則表達式(regular expression),它的主要功能是从字符串(string)中通过特定的模式(pa ...
- 百度地图 创建 自定义控件(vue)
1.组件代码 Bmap.vue <!-- 离线地图 组件 --> <template> <div id="map" :style="styl ...
- 树状数组求最大值 (RMQ with Shifts)
代码: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib ...
- AsyncTask源代码解析
快要毕业了.近期在阿里巴巴校园招聘面试,一面过了,感觉挺轻松,可能是运气好.面试官感觉比我腼腆一些.我俩从android绕到了spring mvc 到数据库悲观锁 到linux 然后又会到了andro ...
- Centos7安装配置ansible运维自动化工具
准备至少两台机器 Centos7,这两台机器都关闭 selinux IP:106.13.118.132 服务端(ansible) masterIP:148.70.60.244 节点 slaver 服务 ...
- pppoe server 搭建
Ubuntu 上搭建 pppoe server sudo apt-get install pppoe $ cat /etc/ppp/pppoe-server-options # PPP options ...
- 1185: [HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1426 Solve ...
- SAM4E单片机之旅——9、UART与MCK之MAINCK
为得到更高的带宽,需要使用更高的波特率.UART波特率的计算已经介绍过了,现在就尝试下调整外设的时钟频率.可以有多种方法调整外设时钟(MCK)的频率,这里先介绍先主要时钟(MAINCK)的设置,其中包 ...