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;
  1. objc_msgSend:返回值类型根据实际调用方法决定,第一个参数:要调用的方法对象,第二个参数:调用的方法SEL,后面是可变参数,可以根据实际调用的方法参数来决定。
  2. 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

 

posted @ 2020-02-19 20:57  zbblogs  阅读(1981)  评论(1编辑  收藏  举报