来历
写给想玩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
网友评论
id (*function1)(id, SEL, BOOL(^)(BOOL b)) = (id (*)(id, SEL, BOOL (^)(BOOL b)))objc_msgSend;
id (*function2)(id, SEL, id) = (id (*)(id, SEL, id))objc_msgSend;
id (*functionSuper)(id, SEL, ...) = (id(*)(id, SEL, ...))objc_msgSendSuper