美文网首页
RunTime的一些知识点之消息发送

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

作者: bonoCat | 来源:发表于2017-05-16 16:35 被阅读98次

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

    了解Runtime首先就要看下他内部是如何实现的可以参考Runtime源码,由于runtime内容比较多,就从不同的点来描述
    注:xcode 需要关闭objc_msgSend 的严格模式 > Enable strict checking of objc_msgSend Calls

    Runtime 消息发送机制

    object C 中 方法的调用、消息的发送Runtime的消息发送机制,源码来自<objc/message.h>

    从一个比较经典的问题入手吧:

    
    @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的一些知识点之消息发送

          本文链接:https://www.haomeiwen.com/subject/beblxxtx.html