美文网首页提升
objc_msgSend()新版本使用

objc_msgSend()新版本使用

作者: it_Xiong | 来源:发表于2019-04-12 11:58 被阅读0次

    很久没有研究runtime方面的知识了,最近在总结下KVO,自己实现一个KVO的过程中,发现objc_msgSend()函数发送消息不能传参,刚好把自己的解决办法分享出来。

    • 老版本
      所谓老版本也就是苹果在未推出新版runtime之前,我们可以肆意的使用objc_msgSend()函数,当时是这样的:
    objc_msgSend(id _Nullable self, SEL _Nonnull op, ...)
    
    • 新版本
      以下是目前版本中objc/message.h中的objc_msgSend()
    objc_msgSend(void /* id self, SEL op, ... */ )
    

    没有参数了肿么办,我就是要传参数啊,不然调用它干嘛...
    个人认为内部依然还是存在这两个参数, 于是去rumtime源码里查看,runtime的苹果源码可以去苹果官网上下载👉runtime源码
    后面发现将这个函数看成c语言的函数声明,通过强制转化类型解决这个问题,这个是runtime源码里面的:

    objc01.png

    也可以像下面这样:

    ((void(*)(id,SEL,NSString *))objc_msgSend)(self,@selector(setName:),newName);
    
    

    或者这样:

         ((void (*)(id, SEL,NSString*,id, NSDictionary<NSString*,id>*,void *))objc_msgSend)(observer, @selector(observeValueForKeyPath:ofObject:change:context:),@"name",self,@{@"name":newName},nil);
    
    

    当然也可以直接转化为新的函数,更加容易调用,例如下面这样:

      id (*function1)(id, SEL, void(^)(NSString* a, NSInteger b)) = (id (*)(id, SEL, void (^)(NSString* a,NSInteger b)))objc_msgSend;
    
      id (*function2)(id, SEL, NSString *) = (id (*)(id, SEL, NSString *))objc_msgSend;
    
    

    使用起来就比较方便:

     function1(self,@selector(setName:),^(NSString* a,NSInteger b){
            
            NSLog(@"%@%ld",a,(long)b);
        });
    
     function2(self,@selector(setName:),newName);
    

    相关文章

      网友评论

        本文标题:objc_msgSend()新版本使用

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