RumeTime程序员iOS Developer

版本变化-objc_msgSend的坑

2016-03-18  本文已影响290人  kuperxu

来历

写给想玩runtime却又难以开启征程的小伙伴。这个函数是包含在头文件<objc/message.h>当中的一个支撑起整个消息发送机制的关键函数。也和OC的runtime机制密不可分。所以随着64位操作系统的出现runtime出现了历史变更,objc_msgSend也出现了变化。

老版本

所谓老版本也就是苹果在未推出新版runtime之前,此时码农们可以肆意的使用objc_msgSend()函数,系统中就默认许可了这样函数的存在:

objc_msgSend(receiver, selector, arg1, arg2, …);

新版本

看系统API发现只剩下一个不带参数的objc_msgSend函数,宝宝心里苦啊,objc_msgSend不带参数我用它干什么,但我们知道这个函数是关键不可能不能调用。于是发现将这个函数看成c语言的函数声明就可以通过强制转化解决这个问题,比如这样

((void ()(id, SEL , NSString))objc_msgSend)((id)p, @selector(setName:),@"33");

返回结构体时,不能使用objc_msgSend,而是要使用objc_msgSend_stret,否则会crash
用objc_msgSend_stret
来发送返回值类型为结构体的消息,使用objc_msgSend_fpret
来发送返回值类型为浮点类型的消息,而又在一些处理器上,还得使用objc_msgSend_fp2ret
来发送返回值类型为浮点类型的消息。

头部就是将这个函数转化成了合适的函数指针即((void ()(id, SEL , NSString)),不清楚可以Google函数指针,这样就可以解决掉不能调用objc_msgSend函数问题,其它变更后续更新!

面试小知识

IMP是一个函数指针,SEL是一个结构体变量,核心是一个字符串可以通过

SEL sel=NSSelectorFromString(@"method");

来创建SEL对象,当然常见的还是@selector()方法。objc_msgSend消息发送会有俩个隐藏参数self和_cmd

上一篇下一篇

猜你喜欢

热点阅读