IMP指针的作用

翻译 2016年06月02日 10:50:49

可能大家一直看到有许多朋友在Runtime相关文章中介绍IMP指针的概念,那么IMP究竟有什么实际作用呢?让我们先从一个函数看起来。

Method Swizzling

如果对Runtime有一定了解的话,一定听说过或者用过这个函数:

void method_exchangeImplementations(Method m1, Method m2)

它通常叫做method swizzling,算是ObjC的"黑魔法"了,作用就是在程序运行期间动态的给两个方法互换实现,比如有这样一种使用场景:


我们的程序中有许多个ViewController,我想在对项目改动最小的情况下,在当每个Controller执行完ViewDidLoad以后就在控制台把自己的名字打印出来,方便我去做调试或者了解项目结构。


有许多朋友会这样说,让所有控制器都继承一个BaseController不就可以了吗?我在这里要解释一下这样做的缺点:假如你的项目里有许多Controller的话,你就需要把项目里凡是没有继承自BaseController的每个Controller都做一次修改了,而且随意更改层级结构会发生意想不到的错误。

其实我们的目的就是重写ViewDidLoad的方法,并在他的方法最后加上几句Log,所以我们需要给UIViewController建立一个category,因为我们知道,如果在Catagory中重写一个方法,就会覆盖它的原有方法实现,但是,这样做以后就没有办法调用系统原有的方法,因为在一个方法里调用自己的方法会是一个死循环。所以我们的解决办法就是,另外写一个方法来和viewDidLoad“交换”,这样外部调用viewDidLoad就会调到新建的这个方法中,同样,我们调用新建的方法就会调用到系统的viewDidLoad中了。


Screen Shot 2015-07-15 at 11.10.02 AM.png

IMP指针

其实,还有一种更加简单的方法可以让我们办到相同的目的,运用IMP指针,IMP就是Implementation的缩写,顾名思义,它是指向一个方法实现的指针,每一个方法都有一个对应的IMP,所以,我们可以直接调用方法的IMP指针,来避免方法调用死循环的问题。

调用一个IMP的方式和调用普通C函数相同,比如:

id returnObjc = someIMP(objc,SEL,params...);

不过如果你的项目没有做其他配置的话这样调用编译器是不会通过的,我们来看一下先它的定义:

if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
else
typedef id (*IMP)(id, SEL, ...); 
endif

在默认情况下你的工程是打开这个配置的


Screen Shot 2015-07-15 at 2.29.56 PM.png

这种情况下IMP被定义为无参数无返回值的函数。所以你需要到工程里搜索到这个选项并把它关闭。这样的麻烦就是,每次使用,你都需要修改工程配置,所以这里我再介绍另外一种办法:重新定义一个和有参数的IMP指针相同的指针类型,在获取IMP时把它强转为此类型。这样运用IMP指针后,就不需要额外的给ViewController写新的方法:


Screen Shot 2015-07-16 at 9.56.19 AM.png

还有一个地方我们需要注意,如果这样直接调用IMP的话就会发生经典的EXC_BAD_ACCESS错误,我们定义的IMP指针是一个有返回值的类型,而其实我们获取的viewDidLoad这个方法是没有返回值的,所以我们需要新定义一个和IMP相同类型的函数指针比如VIMP,把他的返回值定位Void,这样如果你修改的方法有返回值就用IMP,没有返回值就用VIMP。


Screen Shot 2015-07-15 at 5.49.54 PM.png

Screen Shot 2015-07-15 at 3.36.05 PM.png

值得注意的是,如果你重写的方法有返回值,不要忘记在最后做return。

总结

实际上直接调用一个方法的IMP指针的效率是高于调用方法本身的,所以,如果你有一个合适的时机获取到方法的IMP的话,你可以试着调用它。
这是只是IMP使用的场景之一,它还有许多作用,希望大家多多发现。



部分资源来自:/J_雨

iOS开发之旅--_isa和_imp指针

一、回顾 _isa指针 之前谈到过isa指针,isa指针是一个指向所属类的指针,它标注着一个实例对象的真实类型。 在Object-C中消息机制是依靠objc_msgSend()这个函数发送消息, o...
  • toto18369905359
  • toto18369905359
  • 2016年01月28日 17:04
  • 1664

iOS中IMP指针的运用

iOS中IMP指针的运用Runtime中的IMP指针 ios中如果对Runtime有一定了解的话,一定听说过或者用过这个函数 void method_exchangeImplementati...
  • u014466582
  • u014466582
  • 2015年07月28日 17:25
  • 3381

【iOS开发】IMP指针的作用

可能大家一直看到有许多朋友在Runtime相关文章中介绍IMP指针的概念,那么IMP究竟有什么实际作用呢?让我们先从一个函数看起来。Method Swizzling如果对Runtime有一定了解的话,...
  • Hanrovey
  • Hanrovey
  • 2016年07月18日 16:40
  • 324

ios runtime IMP指针 消息转发机制Demo

本文代码是根据消息转发机制来写的 1. UIViewController (ViewDidLoadName)文件 UIViewController的category 在实现viewDidLoad系...
  • xy_26207005
  • xy_26207005
  • 2016年05月12日 17:10
  • 2354

iOS 关于IMP指针的作用

原文地址:http://www.jianshu.com/p/425a39d43d16 可能大家一直看到有许多朋友在Runtime相关文章中介绍IMP指针的概念,那么IMP究竟有什么实际作用呢?让我...
  • xy_26207005
  • xy_26207005
  • 2016年05月12日 14:30
  • 659

iOS中SEL和IMP

我们有时在写iOS程序或者看一些框架代码时会看到SEL和IMP的方法,那这两个到底是什么呢? SEL:类成员方法的指针,但是不同于C语言的函数指针,函数指针直接保存了方法的地址,但SEL只是方法编号;...
  • Dafei_master
  • Dafei_master
  • 2017年05月03日 15:47
  • 396

轻松学习之 IMP指针的作用

可能大家一直看到有许多朋友在Runtime相关文章中介绍IMP指针的概念,那么IMP究竟有什么实际作用呢?让我们先从一个函数看起来。 Method Swizzling 如果对Runti...
  • huangmindong
  • huangmindong
  • 2015年07月20日 10:15
  • 347

轻松学习之三——IMP指针的作用

可能大家一直看到有许多朋友在Runtime相关文章中介绍IMP指针的概念,那么IMP究竟有什么实际作用呢?让我们先从一个函数看起来。 Method Swizzling 如果对Runtime有一定了解的...
  • yuping2901
  • yuping2901
  • 2016年05月13日 10:12
  • 121

imp ignore=y

ignore=y相当于,如果没有的表,创建并倒入数据,如果已经有的表,忽略创建的,但不忽略倒入。 在使用IMP导入并使用ignore=y参数时,ORACLE根本不检查要导入的数据结构和现存在数据库中...
  • jumewo
  • jumewo
  • 2013年10月28日 19:53
  • 3186

C++指针的理解

我们知道,在计算机内存中可以通过变量名称作为标识符访问变量。这种方法,程序不需要关心数据在内存的物理地址;无论何时涉及变量时,它简单地使用标示符。 对于C++程序,计算机的内存就像一系列内存单元的组...
  • shenwanjiang111
  • shenwanjiang111
  • 2016年11月12日 18:41
  • 563
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IMP指针的作用
举报原因:
原因补充:

(最多只允许输入30个字)