iOS Runtime 初识与应用
栏目: Objective-C · 发布时间: 5年前
内容简介:什么是运行时呢?从字面意思来看,就是一个程序在其运行的过程中所做的一些事情。而苹果在 object—C 中提供了一套纯 c 语言的 api,这套 api 即为 runtime。在 iOS 开发的过程中,正式因为runtime 的特性,让 object-C 具有了吸引人的魅力。使得我们可以真正做到玩语言,做出高逼格的花样,快乐就完了~看完上面的流程,可能会迷惑里面提到的一下字端是什么意思,那我们来看一下一个 OC 类中都包含了什么?
什么是运行时呢?从字面意思来看,就是一个程序在其运行的过程中所做的一些事情。而苹果在 object—C 中提供了一套纯 c 语言的 api,这套 api 即为 runtime。
在 iOS 开发的过程中,正式因为runtime 的特性,让 object-C 具有了吸引人的魅力。使得我们可以真正做到玩语言,做出高逼格的花样,快乐就完了~
要了解运行时,我们得先了解 object-C 的消息机制,可以看下面的流程:
1、编译器会先将代码 [obj doSomeThing] 转化为 objc_msgSend(obj, @selector (doSomeThing)) 函数去执行。 2、在 objc_msgSend() 函数中,首先通过 obj 的 isa 指针找到 obj 对应的 class。 3、在 class 中会先去 cache 中 通过 SEL 查找对应函数 doSomeThing(cache 中method 列表是以 SEL 为 key 通过 hash 表来存储的,这样能提高函数查找速度),若 cache 中未找到。再去 class 中的消息列表 methodList 中查找,若 methodList 中未找到,则取 superClass 中查找。若能找到,则将 doSomeThing 加入到 cache中,以方便下次查找,并通过 method 中的函数指针跳转到对应的函数中去执行。
看完上面的流程,可能会迷惑里面提到的一下字端是什么意思,那我们来看一下一个 OC 类中都包含了什么?
可以先看类结构体 struct objc_class。虽然该结构体中有许多变量,但是从变量名中我们可以大概理解其含义,结构体里包含了 指像父类的指针、类名、版本等等信息,里面有些变量会在下面的应用中进行用到。
下面就让我们来看看 runtime 的具体应用吧~
Runtime 的应用
Runtime 的功能非常强大,这也是魅力所在,它能够在程序运行的时候,获取一个类中的所有信息,并且能够根据开发者意愿去修改。脑洞多大,变化就能多大~
接下来,本文主要就下面几点进行讲解:
(1)使用 class_addMethod 函数在运行时对函数进行动态增加新函数
(2)消息转发
(3)使用 class_copyPropertyList 及 property_getName 获取类的属性列表及每个属性的名称
(4) 使用 class_copyMethodList 获取类的所有方法列表
(5) Method Swizzling
动态添加方法 - class_addMethod
首先来看一下 API 文档解释
先看下函数中的各个参数的含义:
Class _Nullable cls:传入的是一个类,也就是你想要在哪个类里进行添加方法
SEL _Nollnull name:想要添加的方法名字
IMP _Nonnull imp:imp 是 Implement 缩写,表示指向方法的实现地址
const char * _Nonnull types:对于参数与返回值的描述。举个例子:"v@:",表示的是返回值为 void 并且没有参数。
下面看一下具体的调用:
这里要给 HJXPerson 类动态添加一个 sayHello 的方法。首先要拿到添加的方法 sayHello 的 IMP 指针,然后调用相应的接口去添加方法。
(注:当要执行动态添加方法的时候,需要用 performSelector 来进行调用,因为 performSelector 是运行时系统负责去找方法的,在编译时候不做任何校验;如果直接调用编译是会自动校验)
消息转发
文章开头介绍了 Objective-C 中调用一个方法的流程,但如果最后都没有找到对应方法,我们的程序都会 crash 并抛出信息没有找到对应的方法。其实在 crash 之前还会进行一套流程,那就是消息转发。转发流程图如下:
下面将分别结合代码事例进行介绍这几种方法的处理:
- resolveInstanceMethod
此为消息转发的先导,也叫动态决议机制。见下面例子:
在 HJXPerson 类中并没有声明 eat 这个函数,所以在实例调用方法的时候会进入到这个回调之中。
其实,objective-c 的方法就是至少带有两个参数(self 和 cmd)的普通的 C 函数。因此在代码中提供这样一个 C 函数 dynamicMethodIMPEat,让它来充当对象方法 eat 这个 selector 的动态实现。
因为 eat 是被对象所调用,所以它被认为是一个对象方法,因而应该在 resolveInstanceMethod 方法中为其提供实现。
- forwardingTargetForSelector
这个方法只能让我们把消息转发到另一个能处理这个消息的对象,但是无法处理消息的内容,比如参数和返回值。例子如下:
该类为 HJXCat 类,里面声明了 “useTool” 这个方法但并没有实现,所以在未添加 resolveInstanceMethod
处理的时候,会进入到 forwardingTargetForSelector 方法中,然后可以根据传入的 aSelector,来转交给其他类去处理相应的方法。
(注:返回的为想要把方法交给的类的一个实例对象)
- forwardInvocation
先看下工程代码
forwardInvocation 的整体流程和 forwardingTargetForSelector 基本上是差不多的。通过 aSelector 来进行判断是否要进行转发,然后进行手动签名。然后在 anInvocation 中可以获取到函数传里过程中所有信息。
forwardingTargetForSelector 和 forwardInvocation 区别:
快速转发: forwardingTargetForSelector 仅支持一个对象的返回,也就是说消息只能被转发给一个对象、无法处理消息的内容,比如参数和返回值。
普通转发: forwardInvocation 可以将消息同时转发给任意多个对象。
消息转发总结
-
首先看是否为该 selector 提供了动态方法决议机制,如果提供了则转到 2;如果没有提供则转到 3;
-
如果动态方法决议真正为该 selector 提供了实现,那么就调用该实现,完成消息发送流程,消息转发就不会进行了;如果没有提供,则转到 3;
-
其次看是否为该 selector 提供了消息转发机制,如果提供了消息了则进行消息转发,此时,无论消息转发是怎样实现的,程序均不会 crash。(因为消息调用的控制权完全交给消息转发机制处理,即使消息转发并没有做任何事情,运行也不会有错误,编译器更不会有错误提示。);如果没提供消息转发机制,则转到 4;
-
运行报错:无法识别的 selector,程序 crash
property_getName 及 class_copyMethodList
这两个函数总从字面意思上,可以看出分别是获取一个类中的所有属性名称及方法名。这两个方法可以算是基础,让你可以知道一个类内的所有属性及方法,以便你接下来可以随心所欲的对于其修改,修改哪里。
下面为调用方法来获取 HJXCat 中的属性及方法:
(上面的各个属性都是声明在 .m 文件中的)
iOS 黑魔法 - Method Swizzling
首先让我们来看下方法交换的原理:
-
在 Objective-C 中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是 selector 的名字。利用 Objective-C 的动态特性,可以实现在运行时偷换 selector 对应的方法实现,达到给方法挂钩的目的。
-
每个类都有一个方法列表,存放着 selector 的名字和方法实现的映射关系。IMP 有点类似函数指针,指向具体的 Method 实现。
归根结底,都是偷换了 selector 的 IMP
跟消息转发相比,Method Swizzling 的做法更为隐蔽,甚至有些冒险,也增大了debug的难度。
下面我们来看一下代码部分:
就这么简简单单几行,就能够实现方法的交换。原有的 eat 方法在调用 hasEatenFull 方法后,就与 play 方法进行了交换,再次执行 eat 方法,其实就是调用了 play 方法。
虽然 Swizzling 可以任你喜欢的去弄,想要玩起来,anyway,都可以。但是开发工程中,我们需要先好好的去想一想,能不能利用良好的代码和架构设计来实现,或者是深入语言的特性来实现。好用,但是不能滥用。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 初识MapReduce的应用场景(附JAVA和Python代码)
- 初识Kubernetes(K8s):从一个单机部署实现Java Web应用例子开始
- 初识Redis
- Netty:初识Netty
- 初识 MQTT
- Webpack2 初识
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
区块链与人工智能:数字经济新时代
高航、俞学劢、王毛路 / 电子工业出版社 / 2018-7-23 / 80
《区块链与人工智能》是畅销书《区块链与新经济:数字货币2.0时代》全新修订升级版。本书是市场上为数不多的系统阐述区块链、人工智能技术与产业的入门级系统教程。从比特币到各类数字货币(代币),从基础原理到应用探讨,全景式呈现区块链与人工智能的发展脉络,既有历史的厚重感也有科技的未来感。本书的另一个亮点是系统整理了区块链创业地图,是一本关于区块链创业、应用、媒体的学习指南,以太坊创始人Vitalik专门......一起来看看 《区块链与人工智能:数字经济新时代》 这本书的介绍吧!