版本变化-objc_msgSend的坑

来历

写给想玩runtime却又难以开启征程的小伙伴。这个函数是包含在头文件当中的一个支撑起整个消息发送机制的关键函数。也和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

你可能感兴趣的:(版本变化-objc_msgSend的坑)