返回

方法选择vs直接调用

IOS

对于熟悉 Objective-C 消息发送的人来说,objc_msgSend 可能是他们最熟悉的函数之一。它是 Objective-C 运行时库的核心部分,负责动态方法分派。

在 Objective-C 中,方法调用是通过消息发送机制来实现的。当一个对象收到一条消息时,运行时库会根据接收者的类和方法选择器来确定要调用的方法。这个过程称为方法选择。

方法选择是一个非常重要的过程,因为它决定了哪个方法会被调用。如果方法选择失败,那么就会导致程序崩溃。为了避免这种情况的发生,Objective-C 运行时库提供了多种方法选择策略。

其中一种方法选择策略是直接调用。当使用直接调用时,运行时库会直接调用接收者类中与方法选择器相匹配的方法。这种方法选择策略非常高效,但它有一个缺点:它只能调用接收者类中定义的方法。

为了克服这个缺点,Objective-C 运行时库提供了另一种方法选择策略:慢速查找。当使用慢速查找时,运行时库会首先在接收者类中查找与方法选择器相匹配的方法。如果在接收者类中找不到匹配的方法,那么运行时库就会继续在接收者的父类中查找。这个过程一直持续到找到匹配的方法为止。

慢速查找比直接调用效率要低,但它可以调用接收者类和父类中定义的方法。因此,慢速查找是一种更加灵活的方法选择策略。

在大多数情况下,直接调用都是最好的方法选择策略。但是,如果需要调用父类中定义的方法,那么就必须使用慢速查找。

objc_msgSend_uncached 函数与 objc_msgSend 函数非常相似,但是它有一个重要的区别:它不会进行方法缓存。这意味着 objc_msgSend_uncached 函数每次调用都会执行完整的方法选择过程。

这使得 objc_msgSend_uncached 函数比 objc_msgSend 函数慢,但它也有一个好处:它可以调用那些没有被缓存的方法。这对于某些特殊情况很有用,例如,当动态生成代码时。

下面是一个使用 objc_msgSend_uncached 函数的示例:

#import <objc/runtime.h>

int main() {
  // 创建一个类
  Class MyClass = objc_allocateClassPair(objc_getClass("NSObject"), "MyClass", 0);

  // 添加一个方法
  objc_registerClassPair(MyClass);

  // 创建一个对象
  id myObject = [[MyClass alloc] init];

  // 调用方法
  objc_msgSend_uncached(myObject, @selector(myMethod));

  return 0;
}

这段代码首先创建了一个名为 MyClass 的类。然后,它向 MyClass 类添加了一个名为 myMethod 的方法。最后,它创建一个 MyClass 对象并调用 myMethod 方法。

注意,objc_msgSend_uncached 函数的第二个参数是一个 SEL 类型的值。SEL 类型的值是方法选择器的唯一标识符。

objc_msgSend_uncached 函数的第三个参数是要调用的方法的参数列表。在这个示例中,myMethod 方法没有参数,所以第三个参数是一个空指针。

objc_msgSend_uncached 函数返回调用的方法的返回值。在这个示例中,myMethod 方法没有返回值,所以 objc_msgSend_uncached 函数返回 void

总之,方法选择是一个非常重要的过程,它决定了哪个方法会被调用。Objective-C 运行时库提供了多种方法选择策略,其中包括直接调用和慢速查找。objc_msgSend_uncached 函数与 objc_msgSend 函数非常相似,但是它有一个重要的区别:它不会进行方法缓存。这使得 objc_msgSend_uncached 函数比 objc_msgSend 函数慢,但它也有一个好处:它可以调用那些没有被缓存的方法。