编写高质量代码的52个有效方法

52个有效方法(11) - 理解objc_msgSend的作用

2018-08-30  本文已影响12人  SkyMing一C
消息机制

OC 语言中,方法调用实际上就是消息发送。

objc_msgSend(id obj, SEL cmd,...)

这是一个参数个数可变的函数,能够接收多个的参数,其中第一个参数代表接收者,第二个参数代码选择子(SEL是选择子的类型),后面其他的消息就是发送消息中所传入的参数。

消息具有“名称”(name)或“选择子”(selector),实际上就是方法名称,可以接受参数,也可以有返回值。

发送消息的方式

在 OC 中我们是这样发送消息的:

id returnValue = [someObject messageName:parameter];

someObject叫做“接受者”(receiver),messageName叫做“选择子”(selector)。选择子与参数合起来称为“消息”(message).编译器看到此消息后,将其转换为一条标准的C语言函数调用,所调用的函数乃是消息传递机制中的核心函数,就是objc_msgSend,编译器把上面的方法调用会转换为如下函数。

id returnValue = objc_msgSend(someObject,@selector(messageName:),parameter);
方法调用的过程
快速映射表

​在调用方法的时候执行的步骤很多,但是objc_msgSend会将匹配到的方法列表中的方法缓存起来,其缓存在一个叫“快速映射表”里面。每一个类都有这样的一块缓存,在该类下次再执行相同的消息的时候就会优先从“快速映射表”中查找,而选择子就是查找方法时所用到的键。

方法调用的优先级

分类(最后参与编译的分类优先) --> 原来类 --> 父类

在OC中,类,对象和方法其实都是一个C的结构体
#if !OBJC_TYPES_DEFINED
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

/// Represents an instance of a class.
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;
#endif

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

typedef struct objc_method *Method;
方法调用的具体实例
objc_msgSend(dog,@selector(eat:),meat);
要点
  1. 消息由接受者、选择子及参数构成。给某对象“发送消息”(invoke a message)也就相当于在该对象上“调用方法”(call a method)。

  2. 发给对象的全部消息都要由“动态消息派发系统”来处理,该系统会查出对应的方法,并执行其代码。

上一篇 下一篇

猜你喜欢

热点阅读