RunTime的一些知识点之消息发送

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

你可能感兴趣的:(RunTime的一些知识点之消息发送)