美文网首页RumeTime程序员iOS Developer
版本变化-objc_msgSend的坑

版本变化-objc_msgSend的坑

作者: kuperxu | 来源:发表于2016-03-18 16:44 被阅读290次

    来历

    写给想玩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

    相关文章

      网友评论

      • GhostClock:几个常用转换:
        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

      本文标题:版本变化-objc_msgSend的坑

      本文链接:https://www.haomeiwen.com/subject/slfhlttx.html