objc_msgSend和objc_msgSendSuper的使用
objc_msgSend:用于对objc对象发送消息,执行objc的方法。
objc_msgSendSuper:同上一样,这里是调用objc父类对象的方法。
使用以上函数之前需要对它们做函数转换后,方可使用,以下是这些函数的注释
These functions must be cast to an appropriate function pointer type before being called.
意思就是:在调用这些函数之前,必须将它们转换为适当的函数指针类型。根据开发文档中的描述我们可知,以上函数对应的描述如下:
OBJC_EXPORT id _Nullable objc_msgSend(id _Nullable self, SEL _Nonnull op, ...) OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0); OBJC_EXPORT id _Nullable objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...) OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
/// Specifies the superclass of an instance.
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained _Nonnull id receiver;
/// Specifies the particular superclass of the instance to message.
#if !defined(__cplusplus) && !__OBJC2__
/* For compatibility with old objc-runtime.h header */
__unsafe_unretained _Nonnull Class class;// 这里是兼容旧版本的objc-runtime.h
#else
__unsafe_unretained _Nonnull Class super_class;
#endif
/* super_class is the first class to search */
};
#endif
这样我们就可以将上面的两个函数转换成如下函数指针:
id (*sendMsg)(id, SEL) = (void *)objc_msgSend;
id (*sendMsgSuper)(void *, SEL) = (void *)objc_msgSendSuper;
- objc_msgSend:返回值类型根据实际调用方法决定,第一个参数:要调用的方法对象,第二个参数:调用的方法SEL,后面是可变参数,可以根据实际调用的方法参数来决定。
- objc_msgSendSuper:返回值类型根据实际调用方法决定,第一个参数:objc_super的struct对象指针,第二个参数:调用的方法SEL,后面是可变参数,可以根据实际调用的方法参数来决定。
事例代码:
1 @interface BaseObj : NSObject 2 3 - (int)add:(int)a b:(int)b; 4 5 @end 6 @implementation BaseObj 7 8 - (int)add:(int)a b:(int)b{ 9 return a+b; 10 } 11 12 @end 13 14 @interface MyObj : BaseObj 15 16 @end 17 18 // 利用runtime调用MyObj父类的add方法 19 MyObj *obj = [[MyObj alloc] init]; 20 21 Class cls = object_getClass(obj); 22 Class superCls = class_getSuperclass(cls); 23 24 struct objc_super obj_super_class = { 25 .receiver = obj, 26 .super_class = superCls 27 }; 28 29 // 将objc_msgSendSuper转换成对应的函数指针 30 int (*add)(void *, SEL, int, int) = (void *)objc_msgSendSuper; 31 // 调用add方法,&操作符是c/c++取指针的操作符 32 int i = add(&obj_super_class, @selector(add:b:), 1, 2); // 这里的返回值类型根据实际调用方法可知,是一个int类型 33 NSLog(@"1+2=%@", @(i));
输出如下:
2020-02-19 20:48:23.524429+0800 Test[1331:133221] 1+2=3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?