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
要得到你必须要付出,要付出你还要学会坚持,如果你真的觉得很难,那你就放弃,但是你放弃了就不要抱怨,我觉得人生就是这样,世界真的是平等的,每个人都要通过自己的努力,去决定自己生活的样子。