返回

iOS 底层:动态方法决议(unrecognized selector 处理流程)

IOS

在前面的两篇文章中,我们探索了消息查找的流程,包括快速查找和慢速查找。在本文中,我们将开始探索消息查找未找到时候的处理流程。unrecognized selector 是我们经常遇到的一个错误,它表示消息发送找不到对应的实现方法。那么,当这种情况发生时,系统是如何处理的呢?

unrecognized selector 的产生

unrecognized selector 错误的产生,通常是因为以下几种情况:

  • 类中没有实现该方法。
  • 方法名写错了。
  • 方法的参数类型不正确。
  • 类和方法的访问权限不正确。

unrecognized selector 的处理流程

unrecognized selector 错误发生时,系统会执行以下步骤:

  1. 系统首先会检查该方法是否已经注册到运行时系统。如果该方法已经注册,那么系统会尝试调用该方法。
  2. 如果该方法没有注册到运行时系统,那么系统会检查该类是否实现了 - (void)forwardInvocation:(NSInvocation *)anInvocation 方法。如果该方法存在,那么系统会调用该方法。
  3. 如果该类没有实现 - (void)forwardInvocation:(NSInvocation *)anInvocation 方法,那么系统会检查该类是否实现了 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法。如果该方法存在,那么系统会调用该方法获取方法签名。
  4. 如果该类没有实现 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法,那么系统会向父类发送 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 消息。
  5. 如果父类也没有实现 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法,那么系统会一直向父类发送消息,直到找到一个实现了该方法的父类。
  6. 如果所有的父类都没有实现 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法,那么系统会抛出 unrecognized selector 错误。

forwardInvocation: 方法

- (void)forwardInvocation:(NSInvocation *)anInvocation 方法是一个特殊的实例方法,它允许我们处理 unrecognized selector 错误。当系统找不到该方法的实现时,它会调用 - (void)forwardInvocation:(NSInvocation *)anInvocation 方法,并将 anInvocation 对象作为参数传递给该方法。

anInvocation 对象包含了以下信息:

  • 方法选择器
  • 方法参数
  • 方法返回值类型

我们可以使用 anInvocation 对象来调用其他方法,或者使用 anInvocation 对象来手动实现该方法。

methodSignatureForSelector: 方法

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法是一个特殊的实例方法,它允许我们获取方法的签名。当系统找不到该方法的实现时,它会调用 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法,并将 aSelector 作为参数传递给该方法。

aSelector 是方法选择器,它是一个指向方法名的指针。

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法返回一个 NSMethodSignature 对象。NSMethodSignature 对象包含了以下信息:

  • 方法返回值类型
  • 方法参数类型
  • 方法调用约定

总结

unrecognized selector 错误的产生,通常是因为以下几种情况:

  • 类中没有实现该方法。
  • 方法名写错了。
  • 方法的参数类型不正确。
  • 类和方法的访问权限不正确。

unrecognized selector 错误发生时,系统会执行以下步骤:

  1. 系统首先会检查该方法是否已经注册到运行时系统。如果该方法已经注册,那么系统会尝试调用该方法。
  2. 如果该方法没有注册到运行时系统,那么系统会检查该类是否实现了 - (void)forwardInvocation:(NSInvocation *)anInvocation 方法。如果该方法存在,那么系统会调用该方法。
  3. 如果该类没有实现 - (void)forwardInvocation:(NSInvocation *)anInvocation 方法,那么系统会检查该类是否实现了 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法。如果该方法存在,那么系统会调用该方法获取方法签名。
  4. 如果该类没有实现 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法,那么系统会向父类发送 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 消息。
  5. 如果父类也没有实现 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法,那么系统会一直向父类发送消息,直到找到一个实现了该方法的父类。
  6. 如果所有的父类都没有实现 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法,那么系统会抛出 unrecognized selector 错误。

我们可以使用 - (void)forwardInvocation:(NSInvocation *)anInvocation 方法和 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 方法来处理 unrecognized selector 错误。