objc_msgSend()新版本使用

很久没有研究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);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,841评论 0 9
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,163评论 1 32
  • 文中的实验代码我放在了这个项目中。 以下内容是我通过整理[这篇博客] (http://yulingtianxia....
    茗涙阅读 955评论 0 6
  • 本文详细整理了 Cocoa 的 Runtime 系统的知识,它使得 Objective-C 如虎添翼,具备了灵活的...
    lylaut阅读 835评论 0 4
  • 一;太子斩手示决绝。荆轲毒誓表心意 太子丹深爱着荆轲,但他也知道荆轲的心并不止属于他一个人。 荆轲也极力的...
    大先生在九楼阅读 330评论 0 2