Runtime之方法交换
在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写、和借助类别重名方法暴力抢先之外,还有就是方法交换
方法交换的原理:在OC中调用一个方法其实是向一个对象发送消息,查找消息的唯一依据是selector的名字。利用OC的动态特性,可以实现在运行时偷换selector方法的实现,达到和方法挂钩的目的。
每一个类都有一个方法列表,存放在selector的名字和方法实现的映射关系,imp有点像函数指针,指向具体的方法实现。
可以利用method_exchanggeimplementations来交换两个方法的imp
可以利用class_replaceMethod来替换方法的imp
可以利用method_setimplementation来直接设置某个方法的imp
归根结底方法交换就是偷换了selector的imp
Method Swizzling 实践
举个例子好了,就替换NSArray的objectAtIndex:方法吧,只需两个步骤。
第一步:自定义一个objectAtIndex:方法,方法名不能和系统的一样
#import <objc/runtime.h>
#import "NSArray+Swizzle.h"
@implementation NSArray (Swizzle)
-(id)ll_ObjectAtIndex:(NSUInteger)index{ if (index < [self count]) { return [self ll_ObjectAtIndex:index]; }else{ return nil; } }
乍一看,这不递归了么?别忘记这是我们准备调换IMP的selector,[self ll_ObjectAtIndex:index] 将会执行真的 [self objectAtIndex:index] 。
第二步:调换IMP
+(void)initialize{
static dispatch_once_t once;
dispatch_once(&once, ^{
Class class = NSClassFromString(@"__NSArrayI");
[self swizzleMethods:class originalSelector:@selector(objectAtIndex:) swizzledSelector:@selector(ll_objectAtIndex:)];
});
}
//方法交换的具体实现
+ (void)swizzleMethods:(Class)class originalSelector:(SEL)origSel swizzledSelector:(SEL)swizSel
{
Method origMethod = class_getInstanceMethod(class, origSel);
Method swizMethod = class_getInstanceMethod(class, swizSel);
//class_addMethod will fail if original method already exists
BOOL didAddMethod = class_addMethod(class, origSel, method_getImplementation(swizMethod), method_getTypeEncoding(swizMethod));
if (didAddMethod) {
class_replaceMethod(class, swizSel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
} else {
//origMethod and swizMethod already exist
method_exchangeImplementations(origMethod, swizMethod);
}
}
@end
定义完毕新方法后,需要弄清楚什么时候实现与系统的方法交互?
既然是给系统的方法添加额外的功能,换句话说,我们以后在开发中都是使用自己定义的方法,取代系统的方法,所以,当程序一启动,就要求能使用自己定义的功能方法.说到这里:我们必须要弄明白一下两个方法 :
+(void)initialize(当类第一次被调用的时候就会调用该方法,整个程序运行中只会调用一次)
+ (void)load(当程序启动的时候就会调用该方法,换句话说,只要程序一启动就会调用load方法,整个程序运行中只会调用一次)
方法交换可以做什么呢
1、防止数组越界
2、统计页面的访问次数(通过交换viewdidload 或者 viewwillappear等方法)
当然还有很多其他的用途,这些只是较为常见的
Runtime之方法交换的更多相关文章
- runtime 实现方法交换 viewwillappear方法
1.新建分类 #import "UIViewController+swizzling.h"#import <objc/runtime.h> @implementatio ...
- 我写的RunTime函数之一,为类的某个属性赋值以及方法交换
1,为属性赋值 #import <UIKit/UIKit.h> @interface UIViewController (RunTime) - (BOOL)setPropertyVal ...
- Runtime 应用(一)拦截系统自带的方法交换实现
动态的交换方法能够给项目中大量已经使用的方法 进行拦截增加操作 实践:利用运行时交换系统的ImageNamed:方法 应用背景 当系统需要适配ios7和ios8时可能会有显示不同图片的需求,但在老项目 ...
- 快速上手Runtime(三)之方法交换
开发过程中,我们经常会用到系统类,而它提供的方法又不能完全满足我们开发的需要,那么在此时,我们需要为系统自带的方法扩展一些功能,而且还要保证原有的功能可正常使用.假设咱们现在有这么一个需求,我们在调用 ...
- runtime之方法的交换
工作中没怎么用到runtime的东西,所以一直没怎么看,现在开始拿起来. runtime之方法的交换: 都知道OC中有category可以对已知类进行扩展,但是假如工程中需要修改某类的原方法,若用ca ...
- iOS 为何使用runtime方法交换多次后却能按照交换顺序依次执行代码逻辑?
题目: 假设我们有一个ViewController, Category A(ViewController), Category B(ViewController), Category C(ViewCo ...
- Runtime之方法
前两篇介绍了类与对象.成员变量&属性&关联对象的相关知识,本篇我们将开始讲解Runtime中最有意思的一部分内容:消息处理机制.我们从一个示例开始. 在OC中,我们使用下面这种方式来调 ...
- OC方法交换swizzle详细介绍——不再有盲点
原文链接:https://www.cnblogs.com/mddblog/p/11105450.html 如果对方法交换已经比较熟悉,可以跳过整体介绍,直接看常见问题部分 整体介绍 方法交换是runt ...
- Java Runtime.availableProcessors()方法
Java Runtime.availableProcessors()方法用法实例教程. 描述 java.lang.Runtime.availableProcessors() 方法返回到Java虚拟 ...
随机推荐
- Java 解决Emoji表情过滤问题
Emoji表情从三方数据中获取没有过滤,导致存入DB的时候报错. 原因: UTF-8编码有可能是两个.三个.四个字节.Emoji表情是4个字节,而Mysql的utf8编码最多3个字节,所以数据插不进去 ...
- Microsoft Windows 实用程序 Sysinternals Utilities Index
最新页面时间:2017年5月16日 Sysinternals被MS收购--windows internals共近70多个工具集 Sysinternals套件 整套Sysinternals Utilit ...
- kali linux终端快捷键设置
kali里面是没有终端快捷键的,需要自己设置. 打开设置->设备->keyboard,拉到最下面点击加号来新建一个快捷键. 名称:打开终端 命令:gnome-terminal 快捷键:Ct ...
- CSS隐藏商务通等内容
CSS隐藏商务通等内容<style>#qiao-wrap{display:none !important;} </style>
- Web基础之Spring IoC
Spring之IoC 概念 IoC:Inversion of Control,中文通常翻译为"控制反转",它还有一个别名叫做依赖注入(Dependency Injection) ...
- WEB前段(HTML+JS),后端(MYSQL+PHP)开发基础
一.HTML HTML:超文本标记语言,可以加载JS/CSS/图片/链接等非文字的内容 一切的网页开发技术都需要建立在HTML的基础之上 HTML的结构和语法 HTML元素 注释: <!-- ...
- POJ2533:Longest Ordered Subsequence
Longest Ordered Subsequence Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 37454 Acc ...
- Python 列表/元组/字典总结
序列是Python中最基本的数据结构.序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推. Python有6个序列的内置类型,但最常见的是列表和元组. 序列 ...
- 开源DDD设计模式框架YMNNetCoreFrameWork第6篇-.net Core Logging和Nlog结合
源码地址:https://github.com/topgunymn/YMNNetCoreFrameWork 遇到的坑:使用了Nlog以后,.NETcore自带的日志等级不起作用,只有nlog配置配置文 ...
- 竟然把Ruoyi在我自己的Eclipse编译成功,并能跑通了。。。。服了我自己了
前几天,下载最新ECLISPSE2019压缩包,解压缩成功,没提示不是免费:eclipse-jee-2019-12-R-win32-x86_64.zip然后我配置好了maven于是我1月2日晚一时兴起 ...