面试题目iOS进阶@IT·互联网

RunTime - 方法交换

2016-12-28  本文已影响101人  陈贺年

上篇我们讲到了runtime 的动态添加属性和方法,遍历对象的属性列表,今天我们来讲一下runtime里面更好用的东西 - 方法交换。

在OC里面,一个方法的基础对象是objc_method
,他的组成结构如下

图1

一个objc_method 里面包含着 一个SEL(方法名),method_types,和一个method_imp(方法实现的指针),method_imp是一个方法对象里最重要的,它指向该方法实现的地址,所以我们平时看到的方法名,它其实不是一个真正的实现者,可以看作是一个方法唯一的标示。

接下来我们要讲的方法交换,其实就是交换方法实现的指针。我们来看一下runtime里面相关的API:

SEL method_getName(Method m)  //获取方法名

IMP method_getImplementation(Method m)//获取方法的指针

 int method_getNumberOfArguments(Method m)//获取方法的参数个数

char *method_copyReturnType(Method m)//获取方法返回值的类型

char *method_copyArgumentType(Method m, unsigned int index)//某个参数的类型

IMP method_setImplementation(Method m, IMP imp)//设置方法的指针(替换方法实现)

method_exchangeImplementations(Method m1, Method m2)//交换方法的指针(交换方法实现)

其中,对指针的操作是方法交换的核心内容,用 method_setImplementation 可以进行方法的替换,用method_exchangeImplementations就可以完成交换 其用法如下,

例子1:

方法替换

图2
图3

在图二中,我在UIImage的分类里将imageNamed:的IMP替换成自己写的replaceImage,所以在图3的实现中,我调用imageNamed:的时候,程序就跑到了我我新替换的指针方法实现。

例2:

方法交换

图4

图4我们用method_exchangeImplementations 将两个方法的IMP进行了互换,当我调用imageNamed:的时候,系统根据imageNamed
:里现有的IMP(已被替换成imageWithName:)去找到执行的地址,当我在return 时执行[self imageWithName:name]方法的时候,系统也会根据该方法的IMP去找到相应要执行的地址。因为imageWithName的IMP已经被替换了,所以我执行 return [self imageWithName:name]并不会产生死循环。

说了那么多,方法交换究竟有什么用????

主要用途:批量修改(重定向),数组临界值的问题,UIViewController生命周期的调取

1.批量修改,如上面的例2,该如我需要新增一个换肤系统,就可以用imageWithName
替换原生的imageName,这样在不改变其他代码的情况下,完成资源的切换。

2.数组临界值的问题,突入其来的数据越界让你的措手不及有没有?解决方法如下

例子3:

在NSarray类别中,新建方法securityObjectAtIndex:,并让他与NSarray的 方法objectAtIndex:交换指针

//临界值

图5

*方法的交换我就讲到这里,下篇我们讲解如何避免 unrecognized selector sent to instance (找不到对象/方法)

上一篇下一篇

猜你喜欢

热点阅读