runtime Method精讲

前言

本篇文章只讲Method的特性及相关方法,不讲Method Swizzling特性。关于Method Swizzling特性,我们放在单独的一篇文章来细讲,因为这一节非常重要。

Method类型

Method类型是一个objc_method结构体指针,而结构体objc_method有三个成员:

Method所有方法

下面是官方所提供的所有Method的方法,我们一一说明其用途,看代码注释:

获取函数列表

我们尝试获取函数列表,并细说函数的参数type encoding、返回值类型等。我们先写以下几个方法:

然后,我们写一个测试方法来调用一下:

其打印结果如下:

从打印结果中,可以看到好多好奇怪的符号。

获取函数名

我们通过method_getName()函数来获取方法SEL

为什么多了两个参数

通过method_getNumberOfArguments获取到函数的所有参数类型,从上面我们所定义的函数中,比如getMethods明明没有参数,为什么会打印出来两个参数呢?而- (int)testInstanceMethod:(NSString *)name andValue:(NSNumber *)value明明只有两个参数,为什么有四个参数呢?下面我们来细说:

id="iframe2456100_0" src="http://pos.baidu.com/lcvm?sz=760x90&rtbid=2385975&rdid=10090296&dc=2&di=2456100&dri=0&dis=0&dai=2&ps=3768x342&dcb=BAIDU_SSP_define&dtm=BAIDU_DUP_SETJSONADSLOT&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1459929845202&ti=runtime%20Method%E7%B2%BE%E8%AE%B2%20%7C%20%E6%A0%87%E5%93%A5%E7%9A%84%E6%8A%80%E6%9C%AF%E5%8D%9A%E5%AE%A2&ari=1&dbv=0&drs=1&pcs=1147x589&pss=1147x3778&cfv=20&cpl=10&chi=1&cce=true&cec=UTF-8&tlm=1459901045&ltu=http%3A%2F%2Fwww.henishuo.com%2Fruntime-method-in-detail%2F&ecd=1&psr=1280x800&par=1276x777&pis=-1x-1&ccd=24&cja=true&cmi=71&col=zh-cn&cdo=-1&tcn=1459929845&qn=af07130ef1808185&dpv=2af45b5e2626fad5&tt=1459929845147.302.381.383" width="760" height="90" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="border-width: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: bottom; max-width: 100%;">

首先,对于第一个方法,它在编译时会被转换成类似这样:

这样一看,知道是有两个参数了吧?

同样的道理,对于第二个方法,在编译时编译器会将其转换成类似这样:

函数编码

通过method_getTypeEncoding获取函数的编码,其结果是一串值。

  • 第一个方法的编码为:v16@0:8
  • 第二个方法的编码为:i32@0:8@16@24
  • 第三个方法的编码为:@24@0:8@16

这么一看,可以看出来什么呢?从这几个值可以看出:

  • 第一个位置是返回值类型,比如第一个方法返回值是V,第二个的是i,第三个的是@
  • 第二/三个位置是第一/二个参数,参数列表从左到右算。分别是@ :,@ :,@ :,都是对象,其实第一个和第二个参数是固定的,第一个是接收消息的对象,而第二个是方法选择器SEL。
  • 如果还有其它参数,依次…

但是类型后面跟着的数字是什么呢?其实笔者也不清楚,文档没有明确说明,不过从其打印结果可以看得出来其规律。比如第一个方法的:@的偏移为0、:的偏移为8、v的偏移为16,其它方法也是类似。

method_invoke

除了使用objc_msgSend函数之外,还可以使用method_invoke,如:

Type Encoding

下面是官方给出的所有类型编码,数据类型的编码最终值会有可能是下面中的多个的组合:

编码值 含意
c 代表char类型
i 代表int类型
s 代表short类型
l 代表long类型,在64位处理器上也是按照32位处理
q 代表long long类型
C 代表unsigned char类型
I 代表unsigned int类型
S 代表unsigned short类型
L 代表unsigned long类型
Q 代表unsigned long long类型
f 代表float类型
d 代表double类型
B 代表C++中的bool或者C99中的_Bool
v 代表void类型
* 代表char *类型
@ 代表对象类型
# 代表类对象 (Class)
: 代表方法selector (SEL)
[array type] 代表array
{name=type…} 代表结构体
(name=type…) 代表union
bnum A bit field of num bits
type A pointer to type
? An unknown type (among other things, this code is used for function pointers)

附属demo链接:https://github.com/CoderJackyHuang/RuntimeDemo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值