轻松学习之 IMP指针的作用

http://www.cocoachina.com/ios/20150717/12623.html

可能大家一直看到有许多朋友在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使用的场景之一,它还有许多作用,希望大家多多发现。

时间: 2024-10-10 15:04:12

轻松学习之 IMP指针的作用的相关文章

轻松学习JavaScript八:JavaScript函数

函数是一组可以随时随地运行的语句,函数作为ECMAScript的核心是很重要的.函数是由事件驱动的或者当它被 调用时执行的可重复使用的代码块.也就是函数是定义一次但却可以调用或执行任意多次的一段JavaScript代码.函 数有时会有参数,即函数被调用时指定了值的局部变量.函数常常使用这些参数来计算一个返回值,这个值也成为函 数调用表达式的值. 一函数声明 函数对于任何语言来说都是一个核心的概念.通过函数可以封装任意多条语句,而且可以在任何地方,任何时候 调用执行.JS中的函数使用functio

ios -- 教你如何轻松学习Swift语法(二)

前言:swift语法基础篇(二)来了,想学习swift的朋友可以拿去参考哦,有兴趣可以相互探讨,共同学习哦. 一.可选类型(重点内容) 1.什么是可选类型? 1.1在OC开发中,如果一个变量暂停不使用,可以赋值为0(基本属性类型)或者赋值为空(对象类型) 1.2在swift开发中,nil也是一个特殊的类型.因为和真实的类型不匹配是不能赋值的(swift是强类型语言) 1.3但是开发中赋值nil,在所难免.因此推出了可选类型 目的:让代码更加严谨 2.可选类型的取值 可选类型要么是:空值 , 要么

轻松学习C语言编程的秘诀:总结+灵感

目前在准备一套C语言的学习教程,所以我这里就以C语言编程的学习来讲.注意,讲的是"轻松学习",那种不注重方法,拼命玩命的方式也有其效果,但不是我提倡的.我讲究的是在方式方法对头.适合你.减轻你学习负担和心里压力的前提下,才适当的抓紧时间. 因此,探索一种很好的学习方法就是我所研究的主要内容. 众所周知,学习C语言并非易事,要学好它更是难上加难.这和你期末考试背会几个题目的答案考上满分没多大关系,也就是说你考试满分也说明不了你学好.学精通了C语言.那么怎么才算学精通C语言?闭着眼睛对自己

SpringMVC轻松学习-其他常用(四)

Spring MVC 3.0 深入 核心原理 1.      用户发送请求给服务器.url:user.do 2.      服务器收到请求.发现DispatchServlet可以处理.于是调用DispatchServlet. 3.      DispatchServlet内部,通过HandleMapping检查这个url有没有对应的Controller.如果有,则调用Controller. 4.      Controller开始执行. 5.      Controller执行完毕后,如果返回字

轻松学习JavaScript十一:JavaScript基本类型(包含类型转换)和引用类型

一值的类型 早在介绍JS的数据类型的时候就提到过基本类型和引用类型,不过在说两种类型之前,我们先来了解一下变量的 值的类型.在ECMAScript中,变量可以存在两种类型的值,即原始值和引用值. (1)原始值 存储在栈中的简单数据段,也就是说,它们的值直接存储在变量访问的位置. (2)引用值 存储在堆中的对象,也就是说,存储在变量处的值是一个指针,指向存储对象的内存处. 为变量赋值时,ECMAScript的解释程序必须判断该值是原始类型,还是引用类型.要实现这一点,解释程序则需 尝试判断该值是否

轻松学习JavaScript十八:JavaScript之DOM简介

一DOM概述 DOM(文档对象模型)是HTML和XML的应用程序接口(API).DOM将把整个页面规划成由节点层级构成的文档. DOM描绘了一个层次化的节点树,运行开发人员添加,移除和修改页面的某一部分.HTML或XML页面的每个部分都 是一个节点的衍生物.通过DOM,可访问HTML文档的所有元素.当网页被加载时,浏览器会创建页面的文档对象模 型,DOM模型被构造为对象的树. DOM是W3C(万维网联盟)的标准.DOM定义了访问HTML和XML文档的标准."W3C 文档对象模型(DOM)是中立

轻松学习linux内核源码的方法

轻松学习Linux操作系统内核源码的方法 针对好多Linux 爱好者对内核很有兴趣却无从下口,本文旨在介绍一种解读linux内核源码的入门方法,而不是解说linux复杂的内核机制:一.核心源程序的文件组织:1.Linux核心源程序通常都安装在/usr/src/linux下,而且它有一个非常简单的编号约定:任何偶数的核心(例如2.0.30)都是一个稳定地发行的核心,而任何奇数的核心(例如2.1.42)都是一个开发中的核心. 本文基于稳定的2.2.5源代码,第二部分的实现平台为 RedHat Lin

黑马程序员学习笔记-C指针小结

黑马程序员学习笔记-C指针 1. 指针简介: 指针是C语言中非常重要的数据类型,是C语言的精华 2. 指针变量定义: 格式:类名标识符 *指针变量名; 指针变量只能存储地址 指针就一个作用:能够根据一个地址值,访问对应的存储空间 指针变量p前面的int:指针变量只能指向int类型的数据 3.实例: 4. 注意点: 指针变量只能存储地址.指针变量未经初始化,不要拿来间接访问其他存储空间.指针变量的初始化可以int *p = &a;也可以拆分成两句:int *p; p =&a;.定义变量时的*

IMP指针和ObjcSendMsg

下边是我整理的一些文档编辑的,那么第一次看可能很生涩难懂,看的时候不要着急,先理解IMP的含义,然后就是C的一些基础一定要知道,这样后面的更容易理解,好了闲话少说 1.那么什么是IMP呢? 其实,还有一种更加简单的方法可以让我们办到相同的目的,运用IMP指针,IMP就是Implementation的缩写,顾名思义,它是指向一个方法实现的指针,每一个方法都有一个对应的IMP,所以,我们可以直接调用方法的IMP指针,来避免方法调用死循环的问题. 调用一个IMP的方式和调用普通C函数相同,比如: 1