RunTime的一些知识点之消息发送
了解Runtime首先就要看下他内部是如何实现的可以参考Runtime源码,由于runtime内容比较多,就从不同的点来描述
注:xcode 需要关闭objc_msgSend 的严格模式 > Enable strict checking of objc_msgSend Calls
Runtime 消息发送机制
object C 中 方法的调用、消息的发送Runtime的消息发送机制,源码来自
从一个比较经典的问题入手吧:
@interface Person : NSObject
@end
@implementation Person
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"Person : %@", [self class]);
NSLog(@"Person : %@", [super class]);
}
return self;
}
@end
@interface Engineer : Person
@end
@implementation Engineer
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"Engineer : %@", [self class]);
NSLog(@"Engineer : %@", [super class]);
}
return self;
}
@end
返回结果
2017-05-16 15:33:23.962 RunTime[1864:61355] Person : Engineer
2017-05-16 15:33:23.963 RunTime[1864:61355] Person : Engineer
2017-05-16 15:33:23.963 RunTime[1864:61355] Engineer : Engineer
2017-05-16 15:33:23.963 RunTime[1864:61355] Engineer : Engineer
如果我们通过 [[Engineer alloc] init] 初始化的话那 [self class] 与 [super class] 都是什么?
下面根据runtime 进行分析:
1. [self class] 执行了什么?
看下 objc_msgSend 的API:
/**
* Sends a message with a simple return value to an instance of a class.
*
* @param self A pointer to the instance of the class that is to receive the message. self
* @param op The selector of the method that handles the message.
* @param ...
* A variable argument list containing the arguments to the method.
*
* @return The return value of the method.
*
* @note When it encounters a method call, the compiler generates a call to one of the
* functions \c objc_msgSend, \c objc_msgSend_stret, \c objc_msgSendSuper, or \c objc_msgSendSuper_stret.
* Messages sent to an object’s superclass (using the \c super keyword) are sent using \c objc_msgSendSuper;
* other messages are sent using \c objc_msgSend. Methods that have data structures as return values
* are sent using \c objc_msgSendSuper_stret and \c objc_msgSend_stret.
*/
OBJC_EXPORT id objc_msgSend(id self, SEL op, ...)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);
可以得出 runtime 方法调用方式: objc_msgSend(self, @selector(class))
从 API 中可以看出 id self 是指向的是实例化的class,用于数据的接收,也就是我们实例化的Engineer
那 class 是什么方法呢?
- (Class)class {
return object_getClass(self);
}
所以, [self class] 可以看成 object_getClass([Engineer alloc])
那么父类和子类中,实例化对象都是Engineer,那么他们返回的都是 Engineer
2.[super class]执行了什么?
看下 objc_msgSendSuper 的API:
/**
* Sends a message with a simple return value to the superclass of an instance of a class.
*
* @param super A pointer to an \c objc_super data structure. Pass values identifying the
* context the message was sent to, including the instance of the class that is to receive the
* message and the superclass at which to start searching for the method implementation.
* super 包含方法的接收者 和 开始搜索方法的实现
* @param op A pointer of type SEL. Pass the selector of the method that will handle the message.
* @param ...
* A variable argument list containing the arguments to the method.
*
* @return The return value of the method identified by \e op.
*
* @see objc_msgSend
*/
OBJC_EXPORT id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);
/// Specifies the superclass of an instance.
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained 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 Class class;
#else
__unsafe_unretained Class super_class;
#endif
/* super_class is the first class to search */
};
可以得出runtime调用方式:
/// Person
struct objc_super sup = {self, [NSObject class]};
objc_msgSendSuper(&sup, @selector(class));
/// Engineer
struct objc_super sup = {self, [Person class]};
objc_msgSendSuper(&sup, @selector(class));
从中可以看出 self 为实例化的class 即 Engineer ,所以 class 的调用是由recevier调用的而搜索的列表会从Person开始,由于 recevier 都是 Engineer,所以返回都是Engineer