IMP指针
可能大家一直看到有许多朋友在Runtime相关文章中介绍IMP指针的概念,那么IMP究竟有什么实际作用呢?让我们先从一个函数看起来。
Method Swizzling
如果对Runtime有一定了解的话,一定听说过或者用过这个函数:
1
|
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中了。
IMP指针
其实,还有一种更加简单的方法可以让我们办到相同的目的,运用IMP指针,IMP就是Implementation的缩写,顾名思义,它是指向一个方法实现的指针,每一个方法都有一个对应的IMP,所以,我们可以直接调用方法的IMP指针,来避免方法调用死循环的问题。
调用一个IMP的方式和调用普通C函数相同,比如:
1
|
id returnObjc = someIMP(objc,SEL,params...); |
不过如果你的项目没有做其他配置的话这样调用编译器是不会通过的,我们来看一下先它的定义:
1
2
3
4
5
|
if !OBJC_OLD_DISPATCH_PROTOTYPES typedef void (*IMP)(void /* id, SEL, ... */ ); else typedef id (*IMP)(id, SEL, ...); endif |
在默认情况下你的工程是打开这个配置的
这种情况下IMP被定义为无参数无返回值的函数。所以你需要到工程里搜索到这个选项并把它关闭。这样的麻烦就是,每次使用,你都需要修改工程配置,所以这里我再介绍另外一种办法:重新定义一个和有参数的IMP指针相同的指针类型,在获取IMP时把它强转为此类型。这样运用IMP指针后,就不需要额外的给ViewController写新的方法:
还有一个地方我们需要注意,如果这样直接调用IMP的话就会发生经典的EXC_BAD_ACCESS错误,我们定义的IMP指针是一个有返回值的类型,而其实我们获取的viewDidLoad这个方法是没有返回值的,所以我们需要新定义一个和IMP相同类型的函数指针比如VIMP,把他的返回值定位Void,这样如果你修改的方法有返回值就用IMP,没有返回值就用VIMP。
值得注意的是,如果你重写的方法有返回值,不要忘记在最后做return。
总结
实际上直接调用一个方法的IMP指针的效率是高于调用方法本身的,所以,如果你有一个合适的时机获取到方法的IMP的话,你可以试着调用它。
IMP指针的更多相关文章
- Runtime之IMP指针,isa指针
要了解 isa 指针先了解下类的定义在xcode中用快捷键Shift+Cmd+O 搜索objc.h 能看到类的定义:了解 Paste_Image.png 可以看出:objc_object:Object ...
- 轻松学习之三——IMP指针的作用
http://www.jianshu.com/p/425a39d43d16 可能大家一直看到有许多朋友在Runtime相关文章中介绍IMP指针的概念,那么IMP究竟有什么实际作用呢?让我们先从一个函数 ...
- 轻松学习之 IMP指针的作用
http://www.cocoachina.com/ios/20150717/12623.html 可能大家一直看到有许多朋友在Runtime相关文章中介绍IMP指针的概念,那么IMP究竟有什么实际作 ...
- iOS 认识runtime 中的三个指针 isa , IMP , SEL
runtime中函数调用经常被提及的三个概念 isa,IMP,SEL 一 isa:是类指针,之所以说isa是指针是因为Class其实是一个指向objc_class结构体的指针,而isa 是它唯一的私 ...
- Method Swizzle黑魔法,修改 ios 系统类库方法 SEL IMP
Method Swizzle黑魔法,修改 ios 系统类库方法 版权声明:本文为博主原创文章,未经博主允许不得转载. 一般来说,系统提供的方法已经足够开发了,但是有的时候有些需求用普通方法不好做. ...
- runtime记录
前言: 最初对于runtime的了解其实只停留在,知道这是一组C的方法,知道消息机制中会把方法调用转成objc_msgSend(theObject,@selector(objectMethod)).随 ...
- Objective-C 2.0的运行时编程
Objective-C 2.0 的运行时环境叫做Morden Runtime,iOS 和Mac OS X 64-bit 的程序都运行在这个环境,也就是说Mac OS X 32-bit 的程序运行在旧的 ...
- EFFECTIVE OBJECTIVE-C 2.0 TIPS 总结 CHAPTER 1 & CHAPTER 2
下面只是对读到的所有 Tips 结合我平时开发中遇到的问题进行总结,每一个 Tips 和书中的每一条对应,本文的目的是去掉书中的大部分讨论的内容,让人能够马上使用这些 Tips,建议阅读过原书后食用更 ...
- objc_msgSend消息传递学习笔记 – 消息转发
该文是 objc_msgSend消息传递学习笔记 – 对象方法消息传递流程 的基础上继续探究源码,请先阅读上文. 消息转发机制(message forwarding) Objective-C 在调用对 ...
随机推荐
- jquery拖拽效果
<!doctype html><html lang="en"><head> <meta charset="utf-8" ...
- table 中的td 字段超长,超过部分用....表示
#contentTable{ table-layout:fixed;}.contentShort{ text-overflow: ellipsis; overflow: hidden; white-s ...
- LeetCode OJ 40. Combination Sum II
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...
- android Tweened Animations
Android提供了两种类型的动画: 一类是Tween动画:提供了旋转.移动.伸展和淡出等效果: 第二类是Frame-by-frame动画:这一类Animations可以创建一个Drawable序列, ...
- Ansible 的委托 并发和任务超时
异步和轮询 Ansible 有时候要执行等待时间很长的操作, 这个操作可能要持续很长时间, 设置超过ssh的timeout. 这时候你可以在step中指定async 和 poll 来实现异步操作 a ...
- 移动端touch触屏滑动事件、滑动触屏事件监听!
一.触摸事件 ontouchstart.ontouchmove.ontouchend.ontouchcancel 目前移动端浏览器均支持这4个触摸事件,包括IE.由于触屏也支持MouseEvent,因 ...
- EF Unit Of Work
BaseEntity, 所有的业务表都继承这个类,每个表的主键都是GUID, 主键名Id. public abstract class BaseEntity{ public BaseEntity() ...
- nginx启动,重启,关闭
1.nginx启动: a. /usr/path/sbin/nginx -c [/etc/path/nginx.conf] 中括号中为指定加载的配置文件,不指定则加载默认配置文件 b. ...
- navicat查询sqlserver数据库编码
首先:查看SQLserver编码格式的SQL语句为: go SELECT COLLATIONPROPERTY('Chinese_PRC_Stroke_CI_AI_KS_WS', 'CodePage' ...
- HDU 2722 Here We Go(relians) Again (spfa)
Here We Go(relians) Again Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/ ...