问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

使用NSInvocation 向对象发送消息

发布网友 发布时间:2023-09-20 15:06

我来回答

1个回答

热心网友 时间:2024-12-05 01:47

�最底层的转发函数为 objc_msgSend ,它的定义如下

从以上的定义我们可以得出一个消息转发包含了几大要素:target、selector、arguments、return value, objc_msgSend 是 C 函数,苹果不提倡我们直接使用该函数来向对象消息。

想必大家都知道使用 performSelector 给对象发送消息,但是其有几个短板

NSInvocation 是苹果工程师们提供的一个高层的消息转发系统。它是一个命令对象,可以给任何 Objective-C 对象类型发送消息,接下来将介绍 NSInvocation 的�用法。

必须使用工厂方法 invocationWithMethodSignature: 来创建一个 NSInvocation 实例。工厂方法的参数是一个 NSMethodSignature 对象。一般使用 NSObject 的实例方法 methodSignatureForSelector: 或者类方法 instanceMethodSignatureForSelector: 来创建对应 selector 的 NSMethodSignature 对象。

例:创建类方法的签名与实例方法签名

需要注意的是 NSMethodSignature 对象仅仅表示了方法的签名:方法的请求、返回数据的编码。所以在使用 NSMethodSignature 来创建 NSInvocation 对象之后仍需指定消息的接收对象和选择子

原则是接收对象的对应选择子需要跟 NSMethodSignature 相匹配。但是根据实践来说,只要不造成 NSInvocation setArgument:atIndex 越界的异常,都是可以成功转发消息的,并且转发成功之后,未赋值的参数都将被赋值为 nil。

例如:

执行结果:

以上为 NSInvocation 类中定义针对参数的操作。 argumentLocation 参数为 void * 类型,表示需要传递指针地址给它。idx 参数是从 2 开始的, 0 和 1 分别代表 target 和 selector,虽然可以�直接使用 getArgument:atIndex 来获取 target 和 selector,但是不如 NSInvocation 的 target 以及 selector 属性来的方便 。需要注意的是当 idx 超过对应 NSMethodSignature的参数个数的时候获取参数和设置参数的方法都会抛出 NSInvalidArgumentException 异常。

例如:给 greetingWithName: 方法传参

需要特别注意 setArgument:atIndex: 默认不会强引用它的 argument,如果 argument 在 NSInvocation 执行的时候之前被释放就会造成野指针异常(EXC_BAD_ACCESS)。

如上图所示, invocation 未�强引用它的 target,在控制器弹出之后,target �被释放,然后再 invoke 这个 invocation 会造成野指针异常。调用 retainArguments 方法来强引用参数(包括 target 以及 selector)

NSInvocation 类中的返回数据的方法如下

可以看到返回数据仍然是通过传入指针来进传值的。例:

输出结果为:

需要注意的是:考虑到 getReturnValue 方法仅仅是将返回数据拷贝到提供的缓存区(retLoc)内,并不会考虑到此处的 内存管理 ,所以如果返回数据是对象类型的,实际上获取到的返回数据是 __unsafe_unretained 类型的,上层函数再�把它作为返回数据返回的时候就会造成野指针异常。通常的解决方法有2种:

第一种:新建一个相同类型的对象并指向它,这样做 result 就会强引用 tempResult,当做返回数据返回之后会自动添加 autorelease 关键字,也就不会造成野指针异常。

第二种:�使用 __bridge 将缓存区转换为 Objective-C 类型,这种做法其实跟第一种相似,但是我们更建议使用这种方式来解决以上问题,因为 getReturnValue �本来就是给缓存区写入数据,缓存区声明为 void* 类型更为合理,然后通过 __bridge 方式转换为 Objective-C 类型并�且将该内存区的内存管理交给 ARC。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
电脑lol突然很卡怎么办啊电脑玩lolfps低怎么解决 危化品仓库有什么设备 香港中文大学2021-2022在河北,重庆最低录取分数线 ChaCheer 洽洽 南瓜子 盐焗味 500g-适用对象 老闫家小粒香南瓜子-适用对象 洽洽盐焗味南瓜子-适用对象 盐焗南瓜子里有添加明矾吗 老街口盐焗味南瓜子500g*2袋量大优惠休闲零食 一天走多少步可以减肥每天走多少步可以减肥 肉炖土豆需要炖多久时间 Carpenters的《Invocation》 歌词 Java/英语:这里的invocation是什么意思 重汽翡翠东郡物业咋样 北方山上常见植物,忘了叫什么了 江苏专转本培训哪家好 无锡兴国专转本机构到底怎么样啊? 从铜锣湾天后总站到鲤鱼门广场怎么坐公交车,最快需要 和平精英qq区转微信区怎么转? 农行社保卡可以网上转账吗 ...家具设计师,一般面试都要注意些什么,请做家具设计的朋友给点面试经验... 邻居家门口放了一只木头象有问题吗 ...一个大象对着我家,是什么意思?对我家有什么影响吗 骄阳映雪刑侦讲了什么 大前门离西城三里河多远 大前门在上海那个方位 玛咖.牛大力,红枣,杞子汤有什么作用 中兴v5max怎么设置usb调试模式 横州市和六景工业园关系 55岁女人退休金句 爽直[shuǎng zhí]什么意思?近义词和反义词是什么?英文翻译是什么? method invocation是什么意思 请懂佛法的大师进 珠光宝气到来无,一路风光领细认;五月莲花开也去,个中消息只君知。是什 ... 假设某竞争性企业的短期成本函数是。求该企业在任意价格下的最小正供 ... 我想问问老侧身睡觉压一面会得偏瘫吗?我现在压的大腿肉疼。谢谢了 ...大腿和臀部肌肉拉伤,睡觉不能平躺,只能侧身睡觉,否则肌肉很疼,正在... 啄木鸟能啄黑砖墙壁吗 释迦摩尼12岁等身像尺寸是多少 龙井茶什么季节喝合适 明前龙井茶什么时候喝最好? ...穿越唐朝 因为时光机 体重错误而穿越有好几个女生一个男生 结局好像... 闯龙宫喜得金箍棒读后感? 苹果手机连笔记本电脑怎么就光听到声音,没看到反应?拜托了各位 谢谢... 电脑没声音了怎么回事,放千千静听不光无声,还无法正常播放 古时有真实历史记载的,道士捉鬼事件么 急~!QQ聊天怎么不能说话,光能听到别人的声音?? 陈焮的英文名怎么写 三顾茅庐在历史上有发生过么?刘备到底怎么请到诸葛亮的? 刘备三请诸葛亮真的吗 为什么刘备能够三顾茅庐,成功地请出诸葛亮