(方法调配)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就介绍这么多吧,希望能够帮助到大家。

相关文章
|
4月前
|
存储 编译器 C++
Method&ConstMethod的内存布局
综上所述,常规方法和常量方法在对象的内存布局中并不直接占据空间;它们作为代码的一部分存储在程序的代码段中。对于虚方法(包括常量虚方法),它们通过VTable在对象中有表示,但即便在这种情况下,方法代码本身也不在对象的内存布局中。理解这些概念有助于深入理解面向对象编程,提高编程效率和代码的可理解性。
43 3
|
6月前
|
Java 测试技术
Java反射之Method的invoke方法详解
Java反射之Method的invoke方法详解
|
Java
Java反射(Method)(三)
日常开发中,我们可使用反射获取JavaBean的方法信息,而描述属性信息的就是Java Method,Method类同样位于java.lang.reflect包下。
189 0
Java反射(Method)(三)
|
iOS开发
Objective-C的hook方案/ Method Swizzling
Method Swizzling是改变一个selector的实际实现的技术。
111 0
|
Java 程序员 C++
Object类九大方法之finalize方法
Object类九大方法之finalize方法
581 0
Object类九大方法之finalize方法
|
Java 程序员
Object类九大方法之getClass方法
Object类九大方法之getClass方法
154 0
Object类九大方法之getClass方法
|
安全 iOS开发
Method Swizzling
Method Swizzling
213 0
Method Swizzling
【Groovy】MOP 元对象协议与元编程 ( 使用 Groovy 元编程进行函数拦截 | 重写 MetaClass#invokeMethod 方法实现函数拦截 | 实现函数调用转发 )
【Groovy】MOP 元对象协议与元编程 ( 使用 Groovy 元编程进行函数拦截 | 重写 MetaClass#invokeMethod 方法实现函数拦截 | 实现函数调用转发 )
158 0
【Groovy】MOP 元对象协议与元编程 ( 使用 Groovy 元编程进行函数拦截 | 重写 MetaClass#invokeMethod 方法实现函数拦截 | 实现函数调用转发 )
|
缓存 安全 Java
Java反射包下的Method类中的Invoke方法
Java反射包下的Method类中的Invoke方法
171 0
Java反射包下的Method类中的Invoke方法

热门文章

最新文章