(方法调配)Method Swizzling
一、概念
方法调配:因为Objective-C是运行时语言,也就是说究竟会调用何种方法要在运行期才能解析出来。那么我们其实也可以在运行时改变选择子名称。这样我们既不需要查看到源代码,又没有必要去重写子类来覆写方法就能改变类本身的功能。这样一来新功能就会在类的所有实例中表现出来,而不仅限于那些重写子类的实例。这种方案就叫做“方法调配”(method swizzling)。
IMP:类方法列表会把选择子的名称映射到方法的实现上,使得动态消息派发系统能够据次找到应该调用的方法,这些方法均以指针的形式来表示,这种指针叫做IMP。其原型如下:
id(* IMP)(id,SEL,.....)
SEL:选择器用于表示一个方法在运行时的名字,一个方法的选择器是一个注册到(或映射到)Objective-C运行时中的C字符串,它是由编译器生成并在类加载的时候被运行时系统自动映射。
一个类(Class)维护一张调度表(dispatch table)用于解析运行时发送的消息;调度表中的每个实体(entry)都是一个方法(Method),其中key值是一个唯一的名字——选择器(SEL),它对应到一个实现(IMP)——实际上就是指向标准C函数的指针。
二、方法调配的实现
首先看两张图片:


以上图2-3是NSString可以相应的选择子lowercaseString,uppercaseString,capitalizedString。每个选择子都映射到了不同的IMP。现在我们通过运行系统提供的方法来将选择子映射表改为2-4所示的映射表。
先简单说一下:我们没有重写子类或者其他,而是修改了方法的布局,这样就会反映到所有的NSString实例上。以下是一些基本的函数操作以及作用:
①、交换方法的实现
void method_exchangeImplementations(Method m1,Method m2)
此方法的参数是两个方法实现,方法实现可以通过以下函数获得:
Method class_getInstanceMethod(Class class,SEL aSelector)
次方法根据给定的选择从类中取出相应的方法。现在举个例子交换lowcaseString和uppercaseString:
Method originMethod = class_getInstanceMethod([NSString class],@selector(lowcaseString));
Method swipMethod = class_getInstanceMethod([NSString class],@selector(uppercaseString)); method_exchangeImplementations(originMethod,swipMethod);
此时如果我们调用NSString的lowcaseString那么实现的结果是uppercaseString的实现。(即如果调用小写转换则是大写转换)。
直接交换的意义不大,我们一般都会用在想重写一个类的方法,然后添加自己的东西,然后将这个方法和类现有的方法进行交换。
②、添加新的方法:
+ (IMP)swizzleSelector:(SEL)origSelector
withIMP:(IMP)newIMP {
Class class = [self class];
Method origMethod = class_getInstanceMethod(class,
origSelector);
IMP origIMP = method_getImplementation(origMethod); if(!class_addMethod(self, origSelector, newIMP,
method_getTypeEncoding(origMethod)))
{
method_setImplementation(origMethod, newIMP);
} return origIMP;
}
具体就不在介绍了。你懂的,,,,
三、总结:
1、在运行期间可以通过方法调配新增或者替换选择子对应方法的实现。
2、使用另一份实现来替换原有的实现,这道程序就叫做方法调配。
3、一定要注意使用,一般来说只有在调试程序的时候才去进行方法调配,很少有人在调试程序之外去直接改动某个类的功能。
四、结束语:
method swizzling就介绍这么多吧,希望能够帮助到大家。
(方法调配)Method Swizzling的更多相关文章
- OBJC运行时方法替换(Method swizzling)
在上周associated objects一文中,我们开始探索Objective-C运行时的一些黑魔法.本周我们继续前行,来讨论可能是最受争议的运行时技术:method swizzling. Me ...
- iOS 11 使用方法替换(Method Swizzling),去掉导航栏返回按钮的文字
方法一:设置BarButtonItem的文本样式为透明颜色,代码如下: [[UIBarButtonItem appearance] setTitleTextAttributes:@{NSForegro ...
- Method Swizzling (方法调配)
Method Swizzling是改变一个selector的实际实现的技术.通过这一技术,我们可以在运行时通过修改类的分发表中selector对应的函数,来修改方法的实现. 例如,我们想跟踪在程序中每 ...
- Objective-C 利用OC的消息机制,使用Method Swizzling进行方法修改
功能:修改父类不可修改函数方法,函数方法交换 应用场景:假如我们使用的他人提供一个的framework,.m已被打包成二进制.a无法修改源码,只留下.h头文件,那假如代码中某个函数出现了问题可以通过这 ...
- Objective-C运行时编程 - 方法混写 Method Swizzling
摘要: 本文描述方法混写对实例.类.父类.不存在的方法等情况处理,属于Objective-C(oc)运行时(runtime)编程范围. 编程环境:Xcode 6.1.1, Yosemite,iOS 8 ...
- Method Swizzling
学习博客: http://www.cocoachina.com/ios/20160121/15076.html (这个作者太牛了,写了我一直想知道的类簇的swizz方法) 一. 一般的swizz 先给 ...
- ios逆向工程-内部钩子(Method Swizzling)
Method Swizzling(方法调配) 怎么说呢,先了解什么是钩子为什么用钩子,学过C++的朋友应该清楚,hook就是用来获得(截断/改变)底层调用的方法.这样我们可以自由的修改或者读取一些想要 ...
- 理解Objective-C Runtime(四)Method Swizzling
Objective-C对象收到消息之后,究竟会调用何种方法需要在运行期间才能解析出来.那你也许会问:与给定的选择子名称相应的方法是不是也可以在runtime改变呢?没错,就是这样.若能善用此特性,则可 ...
- runtime 第四部分method swizzling
接上一篇 http://www.cnblogs.com/ddavidXu/p/5924597.html 转载来源http://www.jianshu.com/p/6b905584f536 http:/ ...
随机推荐
- Java知多少(111)数据库之修改记录
修改数据表记录也有3种方案. 一.使用Statement对象 实现修改数据表记录的SQL语句的语法是: update表名 set 字段名1 = 字段值1,字段名2 = 字段值2,……where特 ...
- 编写高质量JS代码的68个有效方法(十)
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- [OpenCV] Feature Matching
得到了杂乱无章的特征点后,要筛选出好的特征点,也就是good matches. BruteForceMatcher FlannBasedMatcher 两者的区别:http://yangshen998 ...
- 读Java Concurrency in Practice. 第六章.
这一章开讲任务执行.绝大多数并发程序的工作都可以分解为抽象的.互不相关的工作单元,称之为任务(Task). 使用java线程来执行任务 以web服务器的实现举例, 此时将用户的一次连接,当做一个独立的 ...
- UWP开发入门(二十)——键盘弹起时变更界面布局
UWP APP在键盘弹起或隐藏时,并不会自动处理界面布局.有时会出现键盘遮挡了下一个需要填写的文本框,或是下一步按钮的情况.本篇我们以登录界面做例子,用一种巧妙简单的方式在键盘弹起和隐藏时更改界面的布 ...
- angularJs自定义服务
在AngularJS中,系统内置的服务都是以$开头,所以我们的自定义服务尽量避免以$开头.自定义服务的方式有如下几种: 使用Module的provider方法 使用Module的factory方法 使 ...
- C语言编译过程详解
前言 C语言程序从源代码到二进制行程序都经历了那些过程?本文以Linux下C语言的编译过程为例,讲解C语言程序的编译过程. 编写hello world C程序: // hello.c #include ...
- Redis 3.2.100 Windows 32位下载
因为公司的老服务器用的是Windows 2008 32位,不得不安装Redis32位.可在微软的Github上有64位的MSI安装包,前天开始在不同的群里寻找32位的安装包,一直没找到,索性自己下载源 ...
- 2 Orchard汉化资源包的使用
Orchard安装完毕之后我们就可以在后台尝试做一些基本的操作感受下Orchard提供的一些功能,比如添加一个页面.菜单.文章什么的.也可以试着新建一些部件.布局之类的感受下.个人建议摆弄一下了解下就 ...
- 解决死锁SQL
USE [master]GO/****** Object: StoredProcedure [dbo].[p_lockinfo] Script Date: 04/03/2014 15:12:40 ** ...